Skip to content

Commit

Permalink
Sender Key: Track registrationIds in senderKeyState
Browse files Browse the repository at this point in the history
  • Loading branch information
scottnonnenberg-signal committed Jul 30, 2021
1 parent 689542a commit 9fb8114
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 15 deletions.
18 changes: 13 additions & 5 deletions ts/SignalProtocolStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -967,32 +967,37 @@ export class SignalProtocolStore extends EventsMixin {
conversationIds.has(session.fromDB.conversationId)
);
const openEntries: Array<
SessionCacheEntry | undefined
| undefined
| {
entry: SessionCacheEntry;
record: SessionRecord;
}
> = await Promise.all(
entries.map(async entry => {
if (entry.hydrated) {
const record = entry.item;
if (record.hasCurrentState()) {
return entry;
return { record, entry };
}

return undefined;
}

const record = await this._maybeMigrateSession(entry.fromDB);
if (record.hasCurrentState()) {
return entry;
return { record, entry };
}

return undefined;
})
);

const devices = openEntries
.map(entry => {
if (!entry) {
.map(item => {
if (!item) {
return undefined;
}
const { entry, record } = item;

const { conversationId } = entry.fromDB;
conversationIds.delete(conversationId);
Expand All @@ -1015,9 +1020,12 @@ export class SignalProtocolStore extends EventsMixin {
);
}

const registrationId = record.remoteRegistrationId();

return {
identifier,
id,
registrationId,
};
})
.filter(isNotNil);
Expand Down
4 changes: 4 additions & 0 deletions ts/test-electron/SignalProtocolStore_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1330,18 +1330,22 @@ describe('SignalProtocolStore', () => {
{
id: 1,
identifier: number,
registrationId: 243,
},
{
id: 2,
identifier: number,
registrationId: 243,
},
{
id: 3,
identifier: number,
registrationId: 243,
},
{
id: 10,
identifier: number,
registrationId: 243,
},
],
emptyIdentifiers: ['blah', 'blah2'],
Expand Down
7 changes: 7 additions & 0 deletions ts/test-electron/util/sendToGroup_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@ describe('sendToGroup', () => {
{
identifier: 'ident-guid-one',
id: 1,
registrationId: 11,
},
{
identifier: 'ident-guid-one',
id: 2,
registrationId: 22,
},
{
identifier: 'ident-guid-two',
id: 2,
registrationId: 33,
},
];
}
Expand Down Expand Up @@ -60,10 +63,12 @@ describe('sendToGroup', () => {
{
identifier: 'ident-guid-one',
id: 2,
registrationId: 22,
},
{
identifier: 'ident-guid-two',
id: 2,
registrationId: 33,
},
]);
assert.deepEqual(newToMemberUuids, ['ident-guid-one', 'ident-guid-two']);
Expand All @@ -90,10 +95,12 @@ describe('sendToGroup', () => {
{
identifier: 'ident-guid-one',
id: 2,
registrationId: 22,
},
{
identifier: 'ident-guid-two',
id: 2,
registrationId: 33,
},
]);
assert.deepEqual(removedFromMemberUuids, [
Expand Down
1 change: 1 addition & 0 deletions ts/textsecure/Types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export type WebAPICredentials = {
export type DeviceType = {
id: number;
identifier: string;
registrationId: number;
};

// How the legacy APIs generate these types
Expand Down
42 changes: 32 additions & 10 deletions ts/util/sendToGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import {
} from '../textsecure/WebAPI';
import { SignalService as Proto } from '../protobuf';

import { assert } from './assert';
import { strictAssert } from './assert';
import { isGroupV2 } from './whatTypeOfConversation';

const ERROR_EXPIRED_OR_MISSING_DEVICES = 409;
Expand All @@ -56,7 +56,7 @@ const DAY = 24 * HOUR;
const MAX_CONCURRENCY = 5;

// sendWithSenderKey is recursive, but we don't want to loop back too many times.
const MAX_RECURSION = 5;
const MAX_RECURSION = 10;

// TODO: remove once we move away from ArrayBuffers
const FIXMEU8 = Uint8Array;
Expand All @@ -80,7 +80,7 @@ export async function sendToGroup({
sendOptions?: SendOptionsType;
sendType: SendTypesType;
}): Promise<CallbackResultType> {
assert(
strictAssert(
window.textsecure.messaging,
'sendToGroup: textsecure.messaging not available!'
);
Expand Down Expand Up @@ -133,7 +133,7 @@ export async function sendContentMessageToGroup({
timestamp: number;
}): Promise<CallbackResultType> {
const logId = conversation.idForLogging();
assert(
strictAssert(
window.textsecure.messaging,
'sendContentMessageToGroup: textsecure.messaging not available!'
);
Expand Down Expand Up @@ -247,7 +247,7 @@ export async function sendToGroupViaSenderKey(options: {
);
}

assert(
strictAssert(
window.textsecure.messaging,
'sendToGroupViaSenderKey: textsecure.messaging not available!'
);
Expand Down Expand Up @@ -293,14 +293,14 @@ export async function sendToGroupViaSenderKey(options: {
) {
await fetchKeysForIdentifiers(emptyIdentifiers);

// Restart here to capture devices for accounts we just started sesions with
// Restart here to capture devices for accounts we just started sessions with
return sendToGroupViaSenderKey({
...options,
recursionCount: recursionCount + 1,
});
}

assert(
strictAssert(
attributes.senderKeyInfo,
`sendToGroupViaSenderKey/${logId}: expect senderKeyInfo`
);
Expand Down Expand Up @@ -380,6 +380,13 @@ export async function sendToGroupViaSenderKey(options: {
),
{ messageIds: [], sendType: 'senderKeyDistributionMessage' }
);

// Restart here because we might have discovered new or dropped devices as part of
// distributing our sender key.
return sendToGroupViaSenderKey({
...options,
recursionCount: recursionCount + 1,
});
}

// 9. Update memberDevices with both adds and the removals which didn't require a reset.
Expand Down Expand Up @@ -696,7 +703,7 @@ async function handle410Response(
// been re-registered or re-linked.
const senderKeyInfo = conversation.get('senderKeyInfo');
if (senderKeyInfo) {
const devicesToRemove: Array<DeviceType> = devices.staleDevices.map(
const devicesToRemove: Array<PartialDeviceType> = devices.staleDevices.map(
id => ({ id, identifier: uuid })
);
conversation.set({
Expand All @@ -705,7 +712,7 @@ async function handle410Response(
memberDevices: differenceWith(
senderKeyInfo.memberDevices,
devicesToRemove,
deviceComparator
partialDeviceComparator
),
},
});
Expand All @@ -732,7 +739,7 @@ function getXorOfAccessKeys(devices: Array<DeviceType>): Buffer {
const uuids = getUuidsFromDevices(devices);

const result = Buffer.alloc(ACCESS_KEY_LENGTH);
assert(
strictAssert(
result.length === ACCESS_KEY_LENGTH,
'getXorOfAccessKeys starting value'
);
Expand Down Expand Up @@ -876,6 +883,21 @@ function isValidSenderKeyRecipient(
}

function deviceComparator(left?: DeviceType, right?: DeviceType): boolean {
return Boolean(
left &&
right &&
left.id === right.id &&
left.identifier === right.identifier &&
left.registrationId === right.registrationId
);
}

type PartialDeviceType = Omit<DeviceType, 'registrationId'>;

function partialDeviceComparator(
left?: PartialDeviceType,
right?: PartialDeviceType
): boolean {
return Boolean(
left &&
right &&
Expand Down

0 comments on commit 9fb8114

Please sign in to comment.