diff --git a/libloki/test/_test.js b/libloki/test/_test.js index af7726e93..ef33c6a91 100644 --- a/libloki/test/_test.js +++ b/libloki/test/_test.js @@ -1,4 +1,4 @@ -/* global mocha, chai, assert, Whisper */ +/* global window, mocha, chai, assert, Whisper */ mocha.setup('bdd'); window.assert = chai.assert; diff --git a/libloki/test/libloki-protocol_test.js b/libloki/test/libloki-protocol_test.js index 8b3318079..cac7a4330 100644 --- a/libloki/test/libloki-protocol_test.js +++ b/libloki/test/libloki-protocol_test.js @@ -32,14 +32,14 @@ describe('ConversationCollection', () => { it('should encrypt fallback cipher messages as friend requests', async () => { const buffer = new ArrayBuffer(10); const { type } = await fallbackCipher.encrypt(buffer); - assert(type === textsecure.protobuf.Envelope.Type.FRIEND_REQUEST); + assert.strictEqual(type, textsecure.protobuf.Envelope.Type.FRIEND_REQUEST); }); it('should should generate a new prekey bundle for a new contact', async () => { const pubKey = libsignal.crypto.getRandomBytes(32); const pubKeyString = StringView.arrayBufferToHex(pubKey); const preKeyIdBefore = textsecure.storage.get('maxPreKeyId', 1); - const newBundle = await libloki.getPreKeyBundleForNumber(pubKeyString); + const newBundle = await libloki.getPreKeyBundleForContact(pubKeyString); const preKeyIdAfter = textsecure.storage.get('maxPreKeyId', 1); assert.strictEqual(preKeyIdAfter, preKeyIdBefore + 1); @@ -52,62 +52,38 @@ describe('ConversationCollection', () => { assert.isDefined(newBundle.preKey); assert.isDefined(newBundle.signedKey); assert.isDefined(newBundle.signature); - const signedKeyArray = new Uint8Array(newBundle.signedKey.toArrayBuffer()); - assert.strictEqual(testKeyArray.byteLength, signedKeyArray.byteLength); - for (let i = 0 ; i !== testKeyArray.byteLength ; i += 1) - assert.strictEqual(testKeyArray[i], signedKeyArray[i]); + assert.strictEqual(testKeyArray.byteLength, newBundle.signedKey.byteLength); + for (let i = 0 ; i !== testKeyArray.byteLength; i += 1) + assert.strictEqual(testKeyArray[i], newBundle.signedKey[i]); }); it('should should return the same prekey bundle after creating a contact', async () => { const pubKey = libsignal.crypto.getRandomBytes(32); const pubKeyString = StringView.arrayBufferToHex(pubKey); - const bundle1 = await libloki.getPreKeyBundleForNumber(pubKeyString); - const bundle2 = await libloki.getPreKeyBundleForNumber(pubKeyString); - + const bundle1 = await libloki.getPreKeyBundleForContact(pubKeyString); + const bundle2 = await libloki.getPreKeyBundleForContact(pubKeyString); assert.isDefined(bundle1); - assert.isDefined(bundle1.identityKey); - assert.isDefined(bundle1.deviceId); - assert.isDefined(bundle1.preKeyId); - assert.isDefined(bundle1.signedKeyId); - assert.isDefined(bundle1.preKey); - assert.isDefined(bundle1.signedKey); - assert.isDefined(bundle1.signature); - assert.isDefined(bundle2); - assert.isDefined(bundle2.identityKey); - assert.isDefined(bundle2.deviceId); - assert.isDefined(bundle2.preKeyId); - assert.isDefined(bundle2.signedKeyId); - assert.isDefined(bundle2.preKey); - assert.isDefined(bundle2.signedKey); - assert.isDefined(bundle2.signature); - - const identityKeyArray1 = new Uint8Array(bundle1.identityKey.toArrayBuffer()); - const identityKeyArray2 = new Uint8Array(bundle2.identityKey.toArrayBuffer()); - assert.strictEqual(identityKeyArray2.byteLength, identityKeyArray2.byteLength); - for (let i = 0 ; i !== identityKeyArray2.byteLength ; i += 1) - assert.strictEqual(identityKeyArray1[i], identityKeyArray2[i]); - - assert.strictEqual(bundle1.deviceId, bundle2.deviceId); - assert.strictEqual(bundle1.preKeyId, bundle2.preKeyId); - assert.strictEqual(bundle1.signedKeyId, bundle2.signedKeyId); - - const preKeyArray1 = new Uint8Array(bundle1.preKey.toArrayBuffer()); - const preKeyArray2 = new Uint8Array(bundle2.preKey.toArrayBuffer()); - assert.strictEqual(preKeyArray2.byteLength, preKeyArray2.byteLength); - for (let i = 0 ; i !== preKeyArray2.byteLength ; i += 1) - assert.strictEqual(preKeyArray1[i], preKeyArray2[i]); + assert.deepEqual(bundle1, bundle2); + }); - const signedKeyArray1 = new Uint8Array(bundle1.signedKey.toArrayBuffer()); - const signedKeyArray2 = new Uint8Array(bundle2.signedKey.toArrayBuffer()); - assert.strictEqual(signedKeyArray2.byteLength, signedKeyArray2.byteLength); - for (let i = 0 ; i !== signedKeyArray2.byteLength ; i += 1) - assert.strictEqual(signedKeyArray1[i], signedKeyArray2[i]); + it('should save the signed keys and prekeys from a bundle', async () => { + const pubKey = libsignal.crypto.getRandomBytes(32); + const pubKeyString = StringView.arrayBufferToHex(pubKey); + const preKeyIdBefore = textsecure.storage.get('maxPreKeyId', 1); + const newBundle = await libloki.getPreKeyBundleForContact(pubKeyString); + const preKeyIdAfter = textsecure.storage.get('maxPreKeyId', 1); + assert.strictEqual(preKeyIdAfter, preKeyIdBefore + 1); - const signatureArray1 = new Uint8Array(bundle1.signature.toArrayBuffer()); - const signatureArray2 = new Uint8Array(bundle2.signature.toArrayBuffer()); - assert.strictEqual(signatureArray2.byteLength, signatureArray2.byteLength); - for (let i = 0 ; i !== signatureArray2.byteLength ; i += 1) - assert.strictEqual(signatureArray1[i], signatureArray2[i]); + const testKeyArray = new Uint8Array(testKey.pubKey); + assert.isDefined(newBundle); + assert.isDefined(newBundle.identityKey); + assert.isDefined(newBundle.deviceId); + assert.isDefined(newBundle.preKeyId); + assert.isDefined(newBundle.signedKeyId); + assert.isDefined(newBundle.preKey); + assert.isDefined(newBundle.signedKey); + assert.isDefined(newBundle.signature); + assert.deepEqual(testKeyArray, newBundle.signedKey); }); }); diff --git a/libtextsecure/test/in_memory_signal_protocol_store.js b/libtextsecure/test/in_memory_signal_protocol_store.js index 35d5e145d..397a82ff5 100644 --- a/libtextsecure/test/in_memory_signal_protocol_store.js +++ b/libtextsecure/test/in_memory_signal_protocol_store.js @@ -75,16 +75,16 @@ SignalProtocolStore.prototype = { resolve(res); }); }, - storePreKey(keyId, keyPair, contactIdentityKeyString = null) { - if (contactIdentityKeyString) { + storePreKey(keyId, keyPair, contactPubKey= null) { + if (contactPubKey) { const data = { id: keyId, publicKey: keyPair.pubKey, privateKey: keyPair.privKey, - recipient: contactIdentityKeyString, + recipient: contactPubKey, }; return new Promise(resolve => { - resolve(this.put(`25519KeypreKey${contactIdentityKeyString}`, data)); + resolve(this.put(`25519KeypreKey${contactPubKey}`, data)); }); } return new Promise(resolve => { @@ -163,9 +163,9 @@ SignalProtocolStore.prototype = { resolve(deviceIds); }); }, - async loadPreKeyForContactIdentityKeyString(contactIdentityKeyString) { + async loadPreKeyForContact(contactPubKey) { return new Promise(resolve => { - const key = this.get(`25519KeypreKey${contactIdentityKeyString}`); + const key = this.get(`25519KeypreKey${contactPubKey}`); if (!key) resolve(undefined); resolve({ pubKey: key.publicKey, @@ -175,4 +175,32 @@ SignalProtocolStore.prototype = { }); }); }, + async storeContactSignedPreKey(pubKey, signedPreKey) { + const key = { + // id: (autoincrement) + identityKeyString: pubKey, + keyId: signedPreKey.keyId, + publicKey: signedPreKey.publicKey, + signature: signedPreKey.signature, + created_at: Date.now(), + confirmed: false, + }; + this.put(`contactSignedPreKey${pubKey}`, key); + }, + async loadContactSignedPreKey(pubKey) { + const preKey = this.get(`contactSignedPreKey${pubKey}`); + if (preKey) { + return { + id: preKey.id, + identityKeyString: preKey.identityKeyString, + publicKey: preKey.publicKey, + signature: preKey.signature, + created_at: preKey.created_at, + keyId: preKey.keyId, + confirmed: preKey.confirmed, + }; + } + window.log.warn('Failed to fetch contact signed prekey:', pubKey); + return undefined; + }, }; diff --git a/package.json b/package.json index dcaf564a0..cce536cd7 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,9 @@ "prepare-import-build": "node prepare_import_build.js", "publish-to-apt": "NAME=$npm_package_name VERSION=$npm_package_version ./aptly.sh", "test": "yarn test-node && yarn test-electron", - "test-loki": "NODE_ENV=test-loki yarn run start", + "test-view": "NODE_ENV=test yarn run start", + "test-lib-view": "NODE_ENV=test-lib yarn run start", + "test-loki-view": "NODE_ENV=test-loki yarn run start", "test-electron": "yarn grunt test", "test-node": "mocha --recursive test/app test/modules ts/test", "test-node-coverage": "nyc --reporter=lcov --reporter=text mocha --recursive test/app test/modules ts/test",