Receive support for Sender Key

Co-authored-by: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com>
This commit is contained in:
Scott Nonnenberg 2021-05-13 18:18:43 -07:00
parent e5f9c0db28
commit e6bab06510
28 changed files with 743 additions and 164 deletions

View file

@ -4,7 +4,11 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { assert } from 'chai';
import { Direction, SessionRecord } from 'libsignal-client';
import {
Direction,
SenderKeyRecord,
SessionRecord,
} from '@signalapp/signal-client';
import { signal } from '../protobuf/compiled';
import { sessionStructureToArrayBuffer } from '../util/sessionTranslation';
@ -14,7 +18,12 @@ import { clampPrivateKey, setPublicKeyTypeByte } from '../Curve';
import { SignalProtocolStore } from '../SignalProtocolStore';
import { IdentityKeyType, KeyPairType } from '../textsecure/Types.d';
const { RecordStructure, SessionStructure } = signal.proto.storage;
const {
RecordStructure,
SessionStructure,
SenderKeyRecordStructure,
SenderKeyStateStructure,
} = signal.proto.storage;
describe('SignalProtocolStore', () => {
const number = '+5558675309';
@ -47,6 +56,41 @@ describe('SignalProtocolStore', () => {
);
}
function getSenderKeyRecord(): SenderKeyRecord {
const proto = new SenderKeyRecordStructure();
const state = new SenderKeyStateStructure();
state.senderKeyId = 4;
const senderChainKey = new SenderKeyStateStructure.SenderChainKey();
senderChainKey.iteration = 10;
senderChainKey.seed = toUint8Array(getPublicKey());
state.senderChainKey = senderChainKey;
const senderSigningKey = new SenderKeyStateStructure.SenderSigningKey();
senderSigningKey.public = toUint8Array(getPublicKey());
senderSigningKey.private = toUint8Array(getPrivateKey());
state.senderSigningKey = senderSigningKey;
state.senderMessageKeys = [];
const messageKey = new SenderKeyStateStructure.SenderMessageKey();
messageKey.iteration = 234;
messageKey.seed = toUint8Array(getPublicKey());
state.senderMessageKeys.push(messageKey);
proto.senderKeyStates = [];
proto.senderKeyStates.push(state);
return SenderKeyRecord.deserialize(
Buffer.from(
signal.proto.storage.SenderKeyRecordStructure.encode(proto).finish()
)
);
}
function toUint8Array(buffer: ArrayBuffer): Uint8Array {
return new Uint8Array(buffer);
}
@ -109,6 +153,49 @@ describe('SignalProtocolStore', () => {
});
});
describe('senderKeys', () => {
it('roundtrips in memory', async () => {
const distributionId = window.getGuid();
const expected = getSenderKeyRecord();
const deviceId = 1;
const encodedAddress = `${number}.${deviceId}`;
await store.saveSenderKey(encodedAddress, distributionId, expected);
const actual = await store.getSenderKey(encodedAddress, distributionId);
if (!actual) {
throw new Error('getSenderKey returned nothing!');
}
assert.isTrue(
constantTimeEqual(expected.serialize(), actual.serialize())
);
});
it('roundtrips through database', async () => {
const distributionId = window.getGuid();
const expected = getSenderKeyRecord();
const deviceId = 1;
const encodedAddress = `${number}.${deviceId}`;
await store.saveSenderKey(encodedAddress, distributionId, expected);
// Re-fetch from the database to ensure we get the latest database value
await store.hydrateCaches();
const actual = await store.getSenderKey(encodedAddress, distributionId);
if (!actual) {
throw new Error('getSenderKey returned nothing!');
}
assert.isTrue(
constantTimeEqual(expected.serialize(), actual.serialize())
);
});
});
describe('saveIdentity', () => {
const identifier = `${number}.1`;