Remove sealed sender proto file in favor of libsignal types
This commit is contained in:
parent
0e4cdfc566
commit
a0633efece
21 changed files with 132 additions and 230 deletions
|
|
@ -1,70 +0,0 @@
|
|||
// Copyright 2018 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
package signalservice;
|
||||
|
||||
option java_package = "org.whispersystems.libsignal.protocol";
|
||||
option java_outer_classname = "WhisperProtos";
|
||||
|
||||
message ServerCertificate {
|
||||
message Certificate {
|
||||
optional uint32 id = 1;
|
||||
optional bytes key = 2;
|
||||
}
|
||||
|
||||
optional bytes certificate = 1;
|
||||
optional bytes signature = 2;
|
||||
}
|
||||
|
||||
message SenderCertificate {
|
||||
message Certificate {
|
||||
optional string senderE164 = 1;
|
||||
optional string senderUuid = 6;
|
||||
optional uint32 senderDevice = 2;
|
||||
optional fixed64 expires = 3;
|
||||
optional bytes identityKey = 4;
|
||||
optional ServerCertificate signer = 5;
|
||||
}
|
||||
|
||||
optional bytes certificate = 1;
|
||||
optional bytes signature = 2;
|
||||
}
|
||||
|
||||
message UnidentifiedSenderMessage {
|
||||
|
||||
message Message {
|
||||
enum Type {
|
||||
// Our parser does not handle reserved in enums: DESKTOP-1569
|
||||
// reserved 1;
|
||||
MESSAGE = 2;
|
||||
PREKEY_MESSAGE = 3;
|
||||
// Further cases should line up with Envelope.Type, even though old cases don't.
|
||||
|
||||
// reserved 3 to 6;
|
||||
|
||||
SENDERKEY_MESSAGE = 7;
|
||||
PLAINTEXT_CONTENT = 8;
|
||||
}
|
||||
|
||||
enum ContentHint {
|
||||
// Show an error immediately; it was important but we can't retry.
|
||||
DEFAULT = 0;
|
||||
|
||||
// Sender will try to resend; delay any error UI if possible
|
||||
RESENDABLE = 1;
|
||||
|
||||
// Don't show any error UI at all; this is something sent implicitly like a typing message or a receipt
|
||||
IMPLICIT = 2;
|
||||
}
|
||||
|
||||
optional Type type = 1;
|
||||
optional SenderCertificate senderCertificate = 2;
|
||||
optional bytes content = 3;
|
||||
optional ContentHint contentHint = 4;
|
||||
optional bytes groupId = 5;
|
||||
}
|
||||
|
||||
optional bytes ephemeralPublic = 1;
|
||||
optional bytes encryptedStatic = 2;
|
||||
optional bytes encryptedMessage = 3;
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { ContentHint } from '@signalapp/libsignal-client';
|
||||
|
||||
import { handleMessageSend } from '../../util/handleMessageSend';
|
||||
import { getSendOptions } from '../../util/getSendOptions';
|
||||
import {
|
||||
|
|
@ -92,13 +94,11 @@ export async function sendCallingMessage(
|
|||
|
||||
const callMessage = Proto.CallMessage.decode(Bytes.fromBase64(protoBase64));
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
try {
|
||||
if (isGroup(conversation.attributes)) {
|
||||
await handleMessageSend(
|
||||
sendContentMessageToGroup({
|
||||
contentHint: ContentHint.DEFAULT,
|
||||
contentHint: ContentHint.Default,
|
||||
contentMessage: new Proto.Content({ callMessage }),
|
||||
isPartialSend,
|
||||
messageId: undefined,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { ContentHint } from '@signalapp/libsignal-client';
|
||||
import { isNumber } from 'lodash';
|
||||
|
||||
import * as Errors from '../../types/errors';
|
||||
|
|
@ -82,8 +83,7 @@ export async function sendDeleteForEveryone(
|
|||
}
|
||||
|
||||
const sendType = 'deleteForEveryone';
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
const contentHint = ContentHint.RESENDABLE;
|
||||
const contentHint = ContentHint.Resendable;
|
||||
const messageIds = [messageId];
|
||||
|
||||
const deletedForEveryoneSendStatus = message.get(
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { ContentHint } from '@signalapp/libsignal-client';
|
||||
|
||||
import * as Errors from '../../types/errors';
|
||||
import { getSendOptions } from '../../util/getSendOptions';
|
||||
import { isDirectConversation, isMe } from '../../util/whatTypeOfConversation';
|
||||
import { SignalService as Proto } from '../../protobuf';
|
||||
import {
|
||||
handleMultipleSendErrors,
|
||||
maybeExpandErrors,
|
||||
|
|
@ -68,8 +69,7 @@ export async function sendDeleteStoryForEveryone(
|
|||
strictAssert(isStory(message.attributes), 'Story message must be a story');
|
||||
|
||||
const sendType = 'deleteForEveryone';
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
const contentHint = ContentHint.RESENDABLE;
|
||||
const contentHint = ContentHint.Resendable;
|
||||
|
||||
const deletedForEveryoneSendStatus = message.get(
|
||||
'deletedForEveryoneSendStatus'
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { ContentHint } from '@signalapp/libsignal-client';
|
||||
|
||||
import { getSendOptions } from '../../util/getSendOptions';
|
||||
import { isDirectConversation, isMe } from '../../util/whatTypeOfConversation';
|
||||
import { SignalService as Proto } from '../../protobuf';
|
||||
|
|
@ -70,8 +72,7 @@ export async function sendDirectExpirationTimerUpdate(
|
|||
profileKey = await ourProfileKeyService.get();
|
||||
}
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
const contentHint = ContentHint.RESENDABLE;
|
||||
const contentHint = ContentHint.Resendable;
|
||||
|
||||
const sendType = 'expirationTimerUpdate';
|
||||
const flags = Proto.DataMessage.Flags.EXPIRATION_TIMER_UPDATE;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { ContentHint } from '@signalapp/libsignal-client';
|
||||
|
||||
import { getSendOptions } from '../../util/getSendOptions';
|
||||
import { isGroup } from '../../util/whatTypeOfConversation';
|
||||
import { SignalService as Proto } from '../../protobuf';
|
||||
import {
|
||||
handleMultipleSendErrors,
|
||||
maybeExpandErrors,
|
||||
|
|
@ -66,7 +67,6 @@ export async function sendGroupCallUpdate(
|
|||
}
|
||||
|
||||
const sendType = 'callingMessage';
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
const groupV2 = conversation.getGroupV2Info();
|
||||
const sendOptions = await getSendOptions(conversation.attributes);
|
||||
if (!groupV2) {
|
||||
|
|
@ -82,7 +82,7 @@ export async function sendGroupCallUpdate(
|
|||
send: () =>
|
||||
conversation.queueJob(logId, () =>
|
||||
sendToGroup({
|
||||
contentHint: ContentHint.DEFAULT,
|
||||
contentHint: ContentHint.Default,
|
||||
groupSendOptions: {
|
||||
groupCallUpdate: { eraId },
|
||||
groupV2,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { ContentHint } from '@signalapp/libsignal-client';
|
||||
|
||||
import { getSendOptionsForRecipients } from '../../util/getSendOptions';
|
||||
import { isGroupV2 } from '../../util/whatTypeOfConversation';
|
||||
import { SignalService as Proto } from '../../protobuf';
|
||||
import {
|
||||
handleMultipleSendErrors,
|
||||
maybeExpandErrors,
|
||||
|
|
@ -70,8 +71,7 @@ export async function sendGroupUpdate(
|
|||
|
||||
const sendOptions = await getSendOptionsForRecipients(recipients);
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
const contentHint = ContentHint.RESENDABLE;
|
||||
const contentHint = ContentHint.Resendable;
|
||||
const sendType = 'groupChange';
|
||||
|
||||
const groupChange = groupChangeBase64
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
import { isNumber } from 'lodash';
|
||||
import PQueue from 'p-queue';
|
||||
import { ContentHint } from '@signalapp/libsignal-client';
|
||||
|
||||
import * as Errors from '../../types/errors';
|
||||
import { strictAssert } from '../../util/assert';
|
||||
|
|
@ -11,7 +12,6 @@ import { getMessageById } from '../../messages/getMessageById';
|
|||
import type { ConversationModel } from '../../models/conversations';
|
||||
import { isGroup, isGroupV2, isMe } from '../../util/whatTypeOfConversation';
|
||||
import { getSendOptions } from '../../util/getSendOptions';
|
||||
import { SignalService as Proto } from '../../protobuf';
|
||||
import { handleMessageSend } from '../../util/handleMessageSend';
|
||||
import { findAndFormatContact } from '../../util/findAndFormatContact';
|
||||
import { uploadAttachment } from '../../util/uploadAttachment';
|
||||
|
|
@ -302,7 +302,6 @@ export async function sendNormalMessage(
|
|||
} else {
|
||||
const conversationType = conversation.get('type');
|
||||
const sendOptions = await getSendOptions(conversation.attributes);
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
let innerPromise: Promise<CallbackResultType>;
|
||||
if (conversationType === Message.GROUP) {
|
||||
|
|
@ -324,7 +323,7 @@ export async function sendNormalMessage(
|
|||
abortSignal =>
|
||||
sendToGroup({
|
||||
abortSignal,
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
groupSendOptions: {
|
||||
attachments,
|
||||
bodyRanges,
|
||||
|
|
@ -392,7 +391,7 @@ export async function sendNormalMessage(
|
|||
attachments,
|
||||
bodyRanges,
|
||||
contact,
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
deletedForEveryoneTimestamp,
|
||||
expireTimer,
|
||||
expireTimerVersion: conversation.getExpireTimerVersion(),
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { ContentHint } from '@signalapp/libsignal-client';
|
||||
|
||||
import { handleMessageSend } from '../../util/handleMessageSend';
|
||||
import { getSendOptions } from '../../util/getSendOptions';
|
||||
import { isDirectConversation } from '../../util/whatTypeOfConversation';
|
||||
import { SignalService as Proto } from '../../protobuf';
|
||||
import {
|
||||
handleMultipleSendErrors,
|
||||
maybeExpandErrors,
|
||||
|
|
@ -62,8 +63,7 @@ export async function sendNullMessage(
|
|||
);
|
||||
|
||||
const sendOptions = await getSendOptions(conversation.attributes);
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
const contentHint = ContentHint.RESENDABLE;
|
||||
const contentHint = ContentHint.Resendable;
|
||||
const sendType = 'nullMessage';
|
||||
|
||||
// Note: we will send to blocked users, to those still in message request state, etc.
|
||||
|
|
@ -109,7 +109,7 @@ export async function sendNullMessage(
|
|||
abortSignal =>
|
||||
sendToGroup({
|
||||
abortSignal,
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
groupSendOptions: {
|
||||
attachments: [],
|
||||
bodyRanges: [],
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { isNumber } from 'lodash';
|
||||
import { ContentHint } from '@signalapp/libsignal-client';
|
||||
|
||||
import { handleMessageSend } from '../../util/handleMessageSend';
|
||||
import { getSendOptions } from '../../util/getSendOptions';
|
||||
|
|
@ -95,8 +96,7 @@ export async function sendProfileKey(
|
|||
|
||||
const { revision } = data;
|
||||
const sendOptions = await getSendOptions(conversation.attributes);
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
const contentHint = ContentHint.RESENDABLE;
|
||||
const contentHint = ContentHint.Resendable;
|
||||
const sendType = 'profileKeyUpdate';
|
||||
|
||||
let sendPromise: Promise<CallbackResultType>;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { isNumber } from 'lodash';
|
||||
import { ContentHint } from '@signalapp/libsignal-client';
|
||||
|
||||
import * as Errors from '../../types/errors';
|
||||
import { strictAssert } from '../../util/assert';
|
||||
|
|
@ -21,7 +22,6 @@ import {
|
|||
isGroupV2,
|
||||
} from '../../util/whatTypeOfConversation';
|
||||
import { getSendOptions } from '../../util/getSendOptions';
|
||||
import { SignalService as Proto } from '../../protobuf';
|
||||
import { handleMessageSend } from '../../util/handleMessageSend';
|
||||
import { ourProfileKeyService } from '../../services/ourProfileKey';
|
||||
import { canReact, isStory } from '../../state/selectors/message';
|
||||
|
|
@ -211,7 +211,6 @@ export async function sendReaction(
|
|||
successfulConversationIds.add(ourConversationId);
|
||||
} else {
|
||||
const sendOptions = await getSendOptions(conversation.attributes);
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
let promise: Promise<CallbackResultType>;
|
||||
if (isDirectConversation(conversation.attributes)) {
|
||||
|
|
@ -250,7 +249,7 @@ export async function sendReaction(
|
|||
timestamp: pendingReaction.timestamp,
|
||||
expireTimer,
|
||||
expireTimerVersion: conversation.getExpireTimerVersion(),
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
groupId: undefined,
|
||||
profileKey,
|
||||
options: sendOptions,
|
||||
|
|
@ -276,7 +275,7 @@ export async function sendReaction(
|
|||
|
||||
return sendToGroup({
|
||||
abortSignal,
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
groupSendOptions: {
|
||||
groupV2: groupV2Info,
|
||||
reaction: reactionForSend,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
// Copyright 2022 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { PlaintextContent } from '@signalapp/libsignal-client';
|
||||
import { ContentHint, PlaintextContent } from '@signalapp/libsignal-client';
|
||||
|
||||
import { handleMessageSend } from '../../util/handleMessageSend';
|
||||
import { getSendOptions } from '../../util/getSendOptions';
|
||||
import { isDirectConversation } from '../../util/whatTypeOfConversation';
|
||||
import { SignalService as Proto } from '../../protobuf';
|
||||
import {
|
||||
handleMultipleSendErrors,
|
||||
maybeExpandErrors,
|
||||
|
|
@ -98,7 +97,6 @@ export async function sendResendRequest(
|
|||
const plaintext = PlaintextContent.deserialize(
|
||||
Bytes.fromBase64(plaintextBase64)
|
||||
);
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
// We run this job on the queue for the individual sender we want the resend from, but
|
||||
// the original message might have been sent in a group - and that's where we'll put
|
||||
|
|
@ -113,7 +111,7 @@ export async function sendResendRequest(
|
|||
timestamp,
|
||||
recipients: [senderAci],
|
||||
proto: plaintext,
|
||||
contentHint: ContentHint.DEFAULT,
|
||||
contentHint: ContentHint.Default,
|
||||
groupId,
|
||||
options,
|
||||
urgent: false,
|
||||
|
|
@ -124,7 +122,7 @@ export async function sendResendRequest(
|
|||
// Now that we've successfully sent, represent this to the user. Three options:
|
||||
|
||||
// 1. We believe that it could be successfully re-sent, so we'll add a placeholder.
|
||||
if (contentHint === ContentHint.RESENDABLE) {
|
||||
if (contentHint === ContentHint.Resendable) {
|
||||
const { retryPlaceholders } = window.Signal.Services;
|
||||
strictAssert(retryPlaceholders, 'sendResendRequest: adding placeholder');
|
||||
|
||||
|
|
@ -148,7 +146,7 @@ export async function sendResendRequest(
|
|||
|
||||
// 2. This message cannot be resent. We'll show no error and trust the other side to
|
||||
// reset their session.
|
||||
if (contentHint === ContentHint.IMPLICIT) {
|
||||
if (contentHint === ContentHint.Implicit) {
|
||||
log.info('contentHint is IMPLICIT, adding no timeline item.');
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { isEqual } from 'lodash';
|
||||
import { ContentHint } from '@signalapp/libsignal-client';
|
||||
|
||||
import type { UploadedAttachmentType } from '../../types/Attachment';
|
||||
import type { ConversationModel } from '../../models/conversations';
|
||||
import type {
|
||||
|
|
@ -324,8 +326,6 @@ export async function sendStory(
|
|||
return;
|
||||
}
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
const sendOptions = await getSendOptionsForRecipients(
|
||||
pendingSendRecipientServiceIds,
|
||||
{ story: true }
|
||||
|
|
@ -356,7 +356,7 @@ export async function sendStory(
|
|||
contentMessage.storyMessage = storyMessage;
|
||||
|
||||
const innerPromise = sendContentMessageToGroup({
|
||||
contentHint: ContentHint.IMPLICIT,
|
||||
contentHint: ContentHint.Implicit,
|
||||
contentMessage,
|
||||
isPartialSend: false,
|
||||
messageId: undefined,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
import { compact, isNumber, throttle, debounce } from 'lodash';
|
||||
import { v4 as generateGuid } from 'uuid';
|
||||
import PQueue from 'p-queue';
|
||||
import { ContentHint } from '@signalapp/libsignal-client';
|
||||
|
||||
import type { ReadonlyDeep } from 'type-fest';
|
||||
import type {
|
||||
|
|
@ -1377,8 +1378,6 @@ export class ConversationModel {
|
|||
|
||||
const contentMessage = messaging.getTypingContentMessage(content);
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
const sendOptions = {
|
||||
...(await getSendOptions(this.attributes)),
|
||||
online: true,
|
||||
|
|
@ -1386,7 +1385,7 @@ export class ConversationModel {
|
|||
if (isDirectConversation(this.attributes)) {
|
||||
await handleMessageSend(
|
||||
messaging.sendMessageProtoAndWait({
|
||||
contentHint: ContentHint.IMPLICIT,
|
||||
contentHint: ContentHint.Implicit,
|
||||
groupId: undefined,
|
||||
options: sendOptions,
|
||||
proto: contentMessage,
|
||||
|
|
@ -1399,7 +1398,7 @@ export class ConversationModel {
|
|||
} else {
|
||||
await handleMessageSend(
|
||||
sendContentMessageToGroup({
|
||||
contentHint: ContentHint.IMPLICIT,
|
||||
contentHint: ContentHint.Implicit,
|
||||
contentMessage,
|
||||
messageId: undefined,
|
||||
online: true,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright 2021 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { SenderCertificate } from '@signalapp/libsignal-client';
|
||||
|
||||
import type { SerializedCertificateType } from '../textsecure/OutgoingMessage';
|
||||
import {
|
||||
SenderCertificateMode,
|
||||
|
|
@ -14,9 +16,6 @@ import { createLogger } from '../logging/log';
|
|||
import type { StorageInterface } from '../types/Storage.d';
|
||||
import * as Errors from '../types/errors';
|
||||
import type { WebAPIType } from '../textsecure/WebAPI';
|
||||
import { SignalService as Proto } from '../protobuf';
|
||||
|
||||
import SenderCertificate = Proto.SenderCertificate;
|
||||
import { safeParseUnknown } from '../util/schemas';
|
||||
|
||||
const log = createLogger('senderCertificate');
|
||||
|
|
@ -176,11 +175,8 @@ export class SenderCertificateService {
|
|||
return undefined;
|
||||
}
|
||||
const certificate = Bytes.fromBase64(certificateString);
|
||||
const decodedContainer = SenderCertificate.decode(certificate);
|
||||
const decodedCert = decodedContainer.certificate
|
||||
? SenderCertificate.Certificate.decode(decodedContainer.certificate)
|
||||
: undefined;
|
||||
const expires = decodedCert?.expires?.toNumber();
|
||||
const decodedCert = SenderCertificate.deserialize(certificate);
|
||||
const expires = decodedCert.expiration();
|
||||
|
||||
if (!isExpirationValid(expires)) {
|
||||
log.warn(
|
||||
|
|
@ -240,8 +236,8 @@ function modeToLogString(mode: SenderCertificateMode): string {
|
|||
}
|
||||
}
|
||||
|
||||
function isExpirationValid(expiration: unknown): expiration is number {
|
||||
return typeof expiration === 'number' && expiration > Date.now();
|
||||
function isExpirationValid(expiration: number): boolean {
|
||||
return expiration > Date.now();
|
||||
}
|
||||
|
||||
export const senderCertificateService = new SenderCertificateService();
|
||||
|
|
|
|||
|
|
@ -6,18 +6,20 @@
|
|||
|
||||
import { assert } from 'chai';
|
||||
import * as sinon from 'sinon';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import Long from 'long';
|
||||
|
||||
import {
|
||||
IdentityKeyPair,
|
||||
SenderCertificate,
|
||||
ServerCertificate,
|
||||
} from '@signalapp/libsignal-client';
|
||||
|
||||
import * as durations from '../../util/durations';
|
||||
import { drop } from '../../util/drop';
|
||||
import * as Bytes from '../../Bytes';
|
||||
import { SenderCertificateMode } from '../../textsecure/OutgoingMessage';
|
||||
import { SignalService as Proto } from '../../protobuf';
|
||||
|
||||
import { SenderCertificateService } from '../../services/senderCertificate';
|
||||
|
||||
import SenderCertificate = Proto.SenderCertificate;
|
||||
|
||||
describe('SenderCertificateService', () => {
|
||||
const FIFTEEN_MINUTES = 15 * durations.MINUTE;
|
||||
|
||||
|
|
@ -39,14 +41,26 @@ describe('SenderCertificateService', () => {
|
|||
}
|
||||
|
||||
beforeEach(() => {
|
||||
fakeValidCertificate = new SenderCertificate();
|
||||
const fakeTrustRoot = IdentityKeyPair.generate();
|
||||
const fakeServerKey = IdentityKeyPair.generate();
|
||||
const fakeSenderIdentityKey = IdentityKeyPair.generate();
|
||||
const fakeServerCert = ServerCertificate.new(
|
||||
1,
|
||||
fakeServerKey.publicKey,
|
||||
fakeTrustRoot.privateKey
|
||||
);
|
||||
|
||||
fakeValidCertificateExpiry = Date.now() + 604800000;
|
||||
const certificate = new SenderCertificate.Certificate();
|
||||
certificate.expires = Long.fromNumber(fakeValidCertificateExpiry);
|
||||
fakeValidCertificate.certificate =
|
||||
SenderCertificate.Certificate.encode(certificate).finish();
|
||||
fakeValidEncodedCertificate =
|
||||
SenderCertificate.encode(fakeValidCertificate).finish();
|
||||
fakeValidCertificate = SenderCertificate.new(
|
||||
'aaaaaaaa-7000-11eb-b32a-33b8a8a487a6',
|
||||
null,
|
||||
2,
|
||||
fakeSenderIdentityKey.publicKey,
|
||||
fakeValidCertificateExpiry,
|
||||
fakeServerCert,
|
||||
fakeServerKey.privateKey
|
||||
);
|
||||
fakeValidEncodedCertificate = fakeValidCertificate.serialize();
|
||||
|
||||
fakeServer = {
|
||||
isOnline: () => true,
|
||||
|
|
@ -65,7 +79,9 @@ describe('SenderCertificateService', () => {
|
|||
put: sinon.stub().resolves(),
|
||||
remove: sinon.stub().resolves(),
|
||||
};
|
||||
fakeStorage.get.withArgs('uuid_id').returns(`${uuid()}.2`);
|
||||
fakeStorage.get
|
||||
.withArgs('uuid_id')
|
||||
.returns('aaaaaaaa-7000-11eb-b32a-33b8a8a487a6.2');
|
||||
fakeStorage.get.withArgs('password').returns('abc123');
|
||||
});
|
||||
|
||||
|
|
@ -199,15 +215,28 @@ describe('SenderCertificateService', () => {
|
|||
it('returns undefined if the server returns an already-expired certificate', async () => {
|
||||
const service = initializeTestService();
|
||||
|
||||
const expiredCertificate = new SenderCertificate();
|
||||
const certificate = new SenderCertificate.Certificate();
|
||||
certificate.expires = Long.fromNumber(Date.now() - 1000);
|
||||
expiredCertificate.certificate =
|
||||
SenderCertificate.Certificate.encode(certificate).finish();
|
||||
const fakeTrustRoot = IdentityKeyPair.generate();
|
||||
const fakeServerKey = IdentityKeyPair.generate();
|
||||
const fakeSenderIdentityKey = IdentityKeyPair.generate();
|
||||
const fakeServerCert = ServerCertificate.new(
|
||||
1,
|
||||
fakeServerKey.publicKey,
|
||||
fakeTrustRoot.privateKey
|
||||
);
|
||||
|
||||
const expiry = Date.now() - 1000;
|
||||
const expiredCertificate = SenderCertificate.new(
|
||||
'aaaaaaaa-7000-11eb-b32a-33b8a8a487a6',
|
||||
null,
|
||||
1,
|
||||
fakeSenderIdentityKey.publicKey,
|
||||
expiry,
|
||||
fakeServerCert,
|
||||
fakeServerKey.privateKey
|
||||
);
|
||||
|
||||
fakeServer.getSenderCertificate.resolves({
|
||||
certificate: Bytes.toBase64(
|
||||
SenderCertificate.encode(expiredCertificate).finish()
|
||||
),
|
||||
certificate: Bytes.toBase64(expiredCertificate.serialize()),
|
||||
});
|
||||
|
||||
assert.isUndefined(await service.get(SenderCertificateMode.WithE164));
|
||||
|
|
|
|||
|
|
@ -1699,12 +1699,7 @@ export default class MessageReceiver
|
|||
'Missing sender certificate for sealed sender message'
|
||||
);
|
||||
|
||||
const unidentifiedSenderTypeEnum =
|
||||
Proto.UnidentifiedSenderMessage.Message.Type;
|
||||
|
||||
if (
|
||||
messageContent.msgType() === unidentifiedSenderTypeEnum.PLAINTEXT_CONTENT
|
||||
) {
|
||||
if (messageContent.msgType() === CiphertextMessageType.Plaintext) {
|
||||
log.info(
|
||||
`decryptSealedSender(${logId}): ` +
|
||||
'unidentified message/plaintext contents'
|
||||
|
|
@ -1719,9 +1714,7 @@ export default class MessageReceiver
|
|||
};
|
||||
}
|
||||
|
||||
if (
|
||||
messageContent.msgType() === unidentifiedSenderTypeEnum.SENDERKEY_MESSAGE
|
||||
) {
|
||||
if (messageContent.msgType() === CiphertextMessageType.SenderKey) {
|
||||
log.info(
|
||||
`decryptSealedSender(${logId}): ` +
|
||||
'unidentified message/sender key contents'
|
||||
|
|
@ -1777,7 +1770,7 @@ export default class MessageReceiver
|
|||
envelope.sourceDevice
|
||||
);
|
||||
const message =
|
||||
messageContent.msgType() === unidentifiedSenderTypeEnum.PREKEY_MESSAGE
|
||||
messageContent.msgType() === CiphertextMessageType.PreKey
|
||||
? PreKeySignalMessage.deserialize(messageContent.contents())
|
||||
: SignalMessage.deserialize(messageContent.contents());
|
||||
const plaintext = await this.#storage.protocol.enqueueSessionJob(
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import PQueue from 'p-queue';
|
|||
import pMap from 'p-map';
|
||||
import type { PlaintextContent } from '@signalapp/libsignal-client';
|
||||
import {
|
||||
ContentHint,
|
||||
ProtocolAddress,
|
||||
SenderKeyDistributionMessage,
|
||||
} from '@signalapp/libsignal-client';
|
||||
|
|
@ -1381,13 +1382,11 @@ export default class MessageSender {
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return this.sendIndividualProto({
|
||||
serviceId: myAci,
|
||||
proto: contentMessage,
|
||||
timestamp,
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
options,
|
||||
urgent,
|
||||
});
|
||||
|
|
@ -1403,10 +1402,8 @@ export default class MessageSender {
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return {
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
serviceId: myAci,
|
||||
isSyncMessage: true,
|
||||
protoBase64: Bytes.toBase64(
|
||||
|
|
@ -1427,10 +1424,8 @@ export default class MessageSender {
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return {
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
serviceId: myAci,
|
||||
isSyncMessage: true,
|
||||
protoBase64: Bytes.toBase64(
|
||||
|
|
@ -1451,10 +1446,8 @@ export default class MessageSender {
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return {
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
serviceId: myAci,
|
||||
isSyncMessage: true,
|
||||
protoBase64: Bytes.toBase64(
|
||||
|
|
@ -1476,10 +1469,8 @@ export default class MessageSender {
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return {
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
serviceId: myAci,
|
||||
isSyncMessage: true,
|
||||
protoBase64: Bytes.toBase64(
|
||||
|
|
@ -1501,10 +1492,8 @@ export default class MessageSender {
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return {
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
serviceId: myAci,
|
||||
isSyncMessage: true,
|
||||
protoBase64: Bytes.toBase64(
|
||||
|
|
@ -1526,10 +1515,8 @@ export default class MessageSender {
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return {
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
serviceId: myAci,
|
||||
isSyncMessage: true,
|
||||
protoBase64: Bytes.toBase64(
|
||||
|
|
@ -1624,10 +1611,8 @@ export default class MessageSender {
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return {
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
serviceId: myAci,
|
||||
isSyncMessage: true,
|
||||
protoBase64: Bytes.toBase64(
|
||||
|
|
@ -1653,10 +1638,8 @@ export default class MessageSender {
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return {
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
serviceId: myAci,
|
||||
isSyncMessage: true,
|
||||
protoBase64: Bytes.toBase64(
|
||||
|
|
@ -1684,10 +1667,8 @@ export default class MessageSender {
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return {
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
serviceId: ourAci,
|
||||
isSyncMessage: true,
|
||||
protoBase64: Bytes.toBase64(
|
||||
|
|
@ -1722,10 +1703,8 @@ export default class MessageSender {
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return {
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
serviceId: ourAci,
|
||||
isSyncMessage: true,
|
||||
protoBase64: Bytes.toBase64(
|
||||
|
|
@ -1759,13 +1738,11 @@ export default class MessageSender {
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return this.sendIndividualProto({
|
||||
serviceId: myAci,
|
||||
proto: contentMessage,
|
||||
timestamp: Date.now(),
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
options,
|
||||
urgent: true,
|
||||
});
|
||||
|
|
@ -1792,13 +1769,11 @@ export default class MessageSender {
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return this.sendIndividualProto({
|
||||
serviceId: myAci,
|
||||
proto: contentMessage,
|
||||
timestamp: Date.now(),
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
options,
|
||||
urgent: false,
|
||||
});
|
||||
|
|
@ -1839,13 +1814,11 @@ export default class MessageSender {
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return this.sendIndividualProto({
|
||||
serviceId: myAci,
|
||||
proto: contentMessage,
|
||||
timestamp: Date.now(),
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
options,
|
||||
urgent: false,
|
||||
});
|
||||
|
|
@ -1877,10 +1850,8 @@ export default class MessageSender {
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return {
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
serviceId: myAci,
|
||||
isSyncMessage: true,
|
||||
protoBase64: Bytes.toBase64(
|
||||
|
|
@ -1921,10 +1892,8 @@ export default class MessageSender {
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return {
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
serviceId: myAci,
|
||||
isSyncMessage: true,
|
||||
protoBase64: Bytes.toBase64(
|
||||
|
|
@ -1962,10 +1931,8 @@ export default class MessageSender {
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return {
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
serviceId: myAci,
|
||||
isSyncMessage: true,
|
||||
protoBase64: Bytes.toBase64(
|
||||
|
|
@ -2009,10 +1976,8 @@ export default class MessageSender {
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return {
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
serviceId: myAci,
|
||||
isSyncMessage: true,
|
||||
protoBase64: Bytes.toBase64(
|
||||
|
|
@ -2045,13 +2010,11 @@ export default class MessageSender {
|
|||
reason: `sendCallingMessage(${timestamp})`,
|
||||
});
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return this.sendMessageProtoAndWait({
|
||||
timestamp,
|
||||
recipients,
|
||||
proto: contentMessage,
|
||||
contentHint: ContentHint.DEFAULT,
|
||||
contentHint: ContentHint.Default,
|
||||
groupId: undefined,
|
||||
options,
|
||||
urgent,
|
||||
|
|
@ -2134,13 +2097,11 @@ export default class MessageSender {
|
|||
});
|
||||
}
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
return this.sendIndividualProto({
|
||||
serviceId: senderAci,
|
||||
proto: contentMessage,
|
||||
timestamp,
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
options,
|
||||
urgent: false,
|
||||
});
|
||||
|
|
@ -2389,7 +2350,6 @@ export default class MessageSender {
|
|||
options?: Readonly<SendOptionsType>
|
||||
): Promise<CallbackResultType> {
|
||||
const timestamp = Date.now();
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
const contentMessage = await this.getSenderKeyDistributionMessage(
|
||||
distributionId,
|
||||
{
|
||||
|
|
@ -2401,7 +2361,7 @@ export default class MessageSender {
|
|||
const sendLogCallback =
|
||||
serviceIds.length > 1
|
||||
? this.makeSendLogCallback({
|
||||
contentHint: contentHint ?? ContentHint.IMPLICIT,
|
||||
contentHint: contentHint ?? ContentHint.Implicit,
|
||||
proto: Proto.Content.encode(contentMessage).finish(),
|
||||
sendType: 'senderKeyDistributionMessage',
|
||||
timestamp,
|
||||
|
|
@ -2411,7 +2371,7 @@ export default class MessageSender {
|
|||
: undefined;
|
||||
|
||||
return this.sendGroupProto({
|
||||
contentHint: contentHint ?? ContentHint.IMPLICIT,
|
||||
contentHint: contentHint ?? ContentHint.Implicit,
|
||||
groupId,
|
||||
options,
|
||||
proto: contentMessage,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
callIdFromRingId,
|
||||
RingUpdate,
|
||||
} from '@signalapp/ringrtc';
|
||||
import { ContentHint } from '@signalapp/libsignal-client';
|
||||
import { isEqual } from 'lodash';
|
||||
import { strictAssert } from './assert';
|
||||
import { DataReader, DataWriter } from '../sql/Client';
|
||||
|
|
@ -1305,10 +1306,8 @@ async function updateRemoteCallHistory(
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
await singleProtoJobQueue.add({
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
serviceId: ourAci,
|
||||
isSyncMessage: true,
|
||||
protoBase64: Bytes.toBase64(
|
||||
|
|
@ -1468,11 +1467,9 @@ export async function markAllCallHistoryReadAndSync(
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
log.info('markAllCallHistoryReadAndSync: Queueing sync message');
|
||||
await singleProtoJobQueue.add({
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
serviceId: ourAci,
|
||||
isSyncMessage: true,
|
||||
protoBase64: Bytes.toBase64(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
// Copyright 2024 Signal Messenger, LLC
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
import { ContentHint } from '@signalapp/libsignal-client';
|
||||
|
||||
import * as Bytes from '../Bytes';
|
||||
import { CallLinkUpdateSyncType } from '../types/CallLink';
|
||||
import { createLogger } from '../logging/log';
|
||||
|
|
@ -55,10 +58,8 @@ async function _sendCallLinkUpdateSync(
|
|||
const contentMessage = new Proto.Content();
|
||||
contentMessage.syncMessage = syncMessage;
|
||||
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
await singleProtoJobQueue.add({
|
||||
contentHint: ContentHint.RESENDABLE,
|
||||
contentHint: ContentHint.Resendable,
|
||||
serviceId: ourAci,
|
||||
isSyncMessage: true,
|
||||
protoBase64: Bytes.toBase64(
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { differenceWith, omit } from 'lodash';
|
|||
import { v4 as generateUuid } from 'uuid';
|
||||
|
||||
import {
|
||||
ContentHint,
|
||||
ErrorCode,
|
||||
LibSignalErrorBase,
|
||||
groupEncrypt,
|
||||
|
|
@ -293,7 +294,6 @@ export async function sendToGroupViaSenderKey(
|
|||
timestamp,
|
||||
urgent,
|
||||
} = options;
|
||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
||||
|
||||
const logId = `sendToGroupViaSenderKey/${sendTarget.idForLogging()}`;
|
||||
log.info(
|
||||
|
|
@ -312,9 +312,9 @@ export async function sendToGroupViaSenderKey(
|
|||
}
|
||||
|
||||
if (
|
||||
contentHint !== ContentHint.DEFAULT &&
|
||||
contentHint !== ContentHint.RESENDABLE &&
|
||||
contentHint !== ContentHint.IMPLICIT
|
||||
contentHint !== ContentHint.Default &&
|
||||
contentHint !== ContentHint.Resendable &&
|
||||
contentHint !== ContentHint.Implicit
|
||||
) {
|
||||
throw new Error(`${logId}: Invalid contentHint ${contentHint}`);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue