// Copyright 2015-2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only /* global libsignal, textsecure, storage, ConversationController */ describe('SignalProtocolStore', () => { const store = textsecure.storage.protocol; const identifier = '+5558675309'; const identityKey = { pubKey: libsignal.crypto.getRandomBytes(33), privKey: libsignal.crypto.getRandomBytes(32), }; const testKey = { pubKey: libsignal.crypto.getRandomBytes(33), privKey: libsignal.crypto.getRandomBytes(32), }; before(async () => { localStorage.clear(); ConversationController.reset(); // store.hydrateCaches(); await storage.fetch(); await ConversationController.load(); await ConversationController.getOrCreateAndWait(identifier, 'private'); }); it('retrieves my registration id', async () => { store.put('registrationId', 1337); const reg = await store.getLocalRegistrationId(); assert.strictEqual(reg, 1337); }); it('retrieves my identity key', async () => { store.put('identityKey', identityKey); const key = await store.getIdentityKeyPair(); assertEqualArrayBuffers(key.pubKey, identityKey.pubKey); assertEqualArrayBuffers(key.privKey, identityKey.privKey); }); it('stores identity keys', async () => { await store.saveIdentity(identifier, testKey.pubKey); const key = await store.loadIdentityKey(identifier); assertEqualArrayBuffers(key, testKey.pubKey); }); it('returns whether a key is trusted', async () => { const newIdentity = libsignal.crypto.getRandomBytes(33); await store.saveIdentity(identifier, testKey.pubKey); const trusted = await store.isTrustedIdentity(identifier, newIdentity); if (trusted) { throw new Error('Allowed to overwrite identity key'); } }); it('returns whether a key is untrusted', async () => { await store.saveIdentity(identifier, testKey.pubKey); const trusted = await store.isTrustedIdentity(identifier, testKey.pubKey); if (!trusted) { throw new Error('Allowed to overwrite identity key'); } }); it('stores prekeys', async () => { await store.storePreKey(1, testKey); const key = await store.loadPreKey(1); assertEqualArrayBuffers(key.pubKey, testKey.pubKey); assertEqualArrayBuffers(key.privKey, testKey.privKey); }); it('deletes prekeys', async () => { await store.storePreKey(2, testKey); await store.removePreKey(2, testKey); const key = await store.loadPreKey(2); assert.isUndefined(key); }); it('stores signed prekeys', async () => { await store.storeSignedPreKey(3, testKey); const key = await store.loadSignedPreKey(3); assertEqualArrayBuffers(key.pubKey, testKey.pubKey); assertEqualArrayBuffers(key.privKey, testKey.privKey); }); it('deletes signed prekeys', async () => { await store.storeSignedPreKey(4, testKey); await store.removeSignedPreKey(4, testKey); const key = await store.loadSignedPreKey(4); assert.isUndefined(key); }); it('stores sessions', async () => { const testRecord = 'an opaque string'; const devices = [1, 2, 3].map(deviceId => [identifier, deviceId].join('.')); await Promise.all( devices.map(async encodedNumber => { await store.storeSession(encodedNumber, testRecord + encodedNumber); }) ); const records = await Promise.all( devices.map(store.loadSession.bind(store)) ); for (let i = 0, max = records.length; i < max; i += 1) { assert.strictEqual(records[i], testRecord + devices[i]); } }); it('removes all sessions for a number', async () => { const testRecord = 'an opaque string'; const devices = [1, 2, 3].map(deviceId => [identifier, deviceId].join('.')); await Promise.all( devices.map(async encodedNumber => { await store.storeSession(encodedNumber, testRecord + encodedNumber); }) ); await store.removeAllSessions(identifier); const records = await Promise.all( devices.map(store.loadSession.bind(store)) ); for (let i = 0, max = records.length; i < max; i += 1) { assert.isUndefined(records[i]); } }); it('returns deviceIds for a number', async () => { const testRecord = 'an opaque string'; const devices = [1, 2, 3].map(deviceId => [identifier, deviceId].join('.')); await Promise.all( devices.map(async encodedNumber => { await store.storeSession(encodedNumber, testRecord + encodedNumber); }) ); const deviceIds = await store.getDeviceIds(identifier); assert.sameMembers(deviceIds, [1, 2, 3]); }); it('returns empty array for a number with no device ids', async () => { const deviceIds = await store.getDeviceIds('foo'); assert.sameMembers(deviceIds, []); }); });