decrypt/encrypt with libsignal-client, remove libsignal-protocol-javascript

This commit is contained in:
Scott Nonnenberg
2021-04-16 16:13:13 -07:00
parent 37ff4a1df4
commit 86d2a4b5dd
60 changed files with 2508 additions and 28714 deletions

View File

@@ -1,8 +1,6 @@
// Copyright 2017-2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
/* global libsignal */
describe('AccountManager', () => {
let accountManager;
@@ -16,7 +14,7 @@ describe('AccountManager', () => {
const DAY = 1000 * 60 * 60 * 24;
beforeEach(async () => {
const identityKey = await libsignal.KeyHelper.generateIdentityKeyPair();
const identityKey = window.Signal.Curve.generateKeyPair();
originalProtocolStorage = window.textsecure.storage.protocol;
window.textsecure.storage.protocol = {

View File

@@ -64,7 +64,9 @@ describe('GroupBuffer', () => {
avatarBuffer.limit = avatarBuffer.offset;
avatarBuffer.offset = 0;
const groupInfo = new window.textsecure.protobuf.GroupDetails({
id: new Uint8Array([1, 3, 3, 7]).buffer,
id: window.Signal.Crypto.typedArrayToArrayBuffer(
new Uint8Array([1, 3, 3, 7])
),
name: 'Hackers',
membersE164: ['cereal', 'burn', 'phreak', 'joey'],
avatar: { contentType: 'image/jpeg', length: avatarLen },
@@ -92,7 +94,9 @@ describe('GroupBuffer', () => {
assert.strictEqual(group.name, 'Hackers');
assertEqualArrayBuffers(
group.id.toArrayBuffer(),
new Uint8Array([1, 3, 3, 7]).buffer
window.Signal.Crypto.typedArrayToArrayBuffer(
new Uint8Array([1, 3, 3, 7])
)
);
assert.sameMembers(group.membersE164, [
'cereal',

View File

@@ -1,7 +1,7 @@
// Copyright 2015-2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
/* global libsignal, textsecure */
/* global textsecure */
describe('encrypting and decrypting profile data', () => {
const NAME_PADDED_LENGTH = 53;
@@ -9,7 +9,7 @@ describe('encrypting and decrypting profile data', () => {
it('pads, encrypts, decrypts, and unpads a short string', () => {
const name = 'Alice';
const buffer = dcodeIO.ByteBuffer.wrap(name).toArrayBuffer();
const key = libsignal.crypto.getRandomBytes(32);
const key = window.Signal.Crypto.getRandomBytes(32);
return textsecure.crypto
.encryptProfileName(buffer, key)
@@ -29,7 +29,7 @@ describe('encrypting and decrypting profile data', () => {
it('handles a given name of the max, 53 characters', () => {
const name = '01234567890123456789012345678901234567890123456789123';
const buffer = dcodeIO.ByteBuffer.wrap(name).toArrayBuffer();
const key = libsignal.crypto.getRandomBytes(32);
const key = window.Signal.Crypto.getRandomBytes(32);
return textsecure.crypto
.encryptProfileName(buffer, key)
@@ -49,7 +49,7 @@ describe('encrypting and decrypting profile data', () => {
it('handles family/given name of the max, 53 characters', () => {
const name = '01234567890123456789\u000001234567890123456789012345678912';
const buffer = dcodeIO.ByteBuffer.wrap(name).toArrayBuffer();
const key = libsignal.crypto.getRandomBytes(32);
const key = window.Signal.Crypto.getRandomBytes(32);
return textsecure.crypto
.encryptProfileName(buffer, key)
@@ -72,7 +72,7 @@ describe('encrypting and decrypting profile data', () => {
it('handles a string with family/given name', () => {
const name = 'Alice\0Jones';
const buffer = dcodeIO.ByteBuffer.wrap(name).toArrayBuffer();
const key = libsignal.crypto.getRandomBytes(32);
const key = window.Signal.Crypto.getRandomBytes(32);
return textsecure.crypto
.encryptProfileName(buffer, key)
@@ -92,25 +92,20 @@ describe('encrypting and decrypting profile data', () => {
});
});
});
it('works for empty string', () => {
it('works for empty string', async () => {
const name = dcodeIO.ByteBuffer.wrap('').toArrayBuffer();
const key = libsignal.crypto.getRandomBytes(32);
const key = window.Signal.Crypto.getRandomBytes(32);
return textsecure.crypto
.encryptProfileName(name.buffer, key)
.then(encrypted => {
assert(encrypted.byteLength === NAME_PADDED_LENGTH + 16 + 12);
return textsecure.crypto
.decryptProfileName(encrypted, key)
.then(({ given, family }) => {
assert.strictEqual(family, null);
assert.strictEqual(given.byteLength, 0);
assert.strictEqual(
dcodeIO.ByteBuffer.wrap(given).toString('utf8'),
''
);
});
});
const encrypted = await textsecure.crypto.encryptProfileName(name, key);
assert(encrypted.byteLength === NAME_PADDED_LENGTH + 16 + 12);
const { given, family } = await textsecure.crypto.decryptProfileName(
encrypted,
key
);
assert.strictEqual(family, null);
assert.strictEqual(given.byteLength, 0);
assert.strictEqual(dcodeIO.ByteBuffer.wrap(given).toString('utf8'), '');
});
});
describe('encrypting and decrypting profile avatars', () => {
@@ -118,7 +113,7 @@ describe('encrypting and decrypting profile data', () => {
const buffer = dcodeIO.ByteBuffer.wrap(
'This is an avatar'
).toArrayBuffer();
const key = libsignal.crypto.getRandomBytes(32);
const key = window.Signal.Crypto.getRandomBytes(32);
return textsecure.crypto.encryptProfile(buffer, key).then(encrypted => {
assert(encrypted.byteLength === buffer.byteLength + 16 + 12);
@@ -133,8 +128,8 @@ describe('encrypting and decrypting profile data', () => {
const buffer = dcodeIO.ByteBuffer.wrap(
'This is an avatar'
).toArrayBuffer();
const key = libsignal.crypto.getRandomBytes(32);
const badKey = libsignal.crypto.getRandomBytes(32);
const key = window.Signal.Crypto.getRandomBytes(32);
const badKey = window.Signal.Crypto.getRandomBytes(32);
return textsecure.crypto.encryptProfile(buffer, key).then(encrypted => {
assert(encrypted.byteLength === buffer.byteLength + 16 + 12);

View File

@@ -1,7 +1,7 @@
// Copyright 2015-2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
/* global libsignal, textsecure */
/* global textsecure */
describe('Key generation', function thisNeeded() {
const count = 10;
@@ -43,11 +43,10 @@ describe('Key generation', function thisNeeded() {
});
}
before(() => {
before(async () => {
localStorage.clear();
return libsignal.KeyHelper.generateIdentityKeyPair().then(keyPair =>
textsecure.storage.protocol.put('identityKey', keyPair)
);
const keyPair = window.Signal.Curve.generateKeyPair();
await textsecure.storage.protocol.put('identityKey', keyPair);
});
describe('the first time', () => {

View File

@@ -6,7 +6,6 @@ function SignalProtocolStore() {
}
SignalProtocolStore.prototype = {
Direction: { SENDING: 1, RECEIVING: 2 },
VerifiedStatus: {
DEFAULT: 0,
VERIFIED: 1,

View File

@@ -21,7 +21,6 @@
<script type="text/javascript" src="in_memory_signal_protocol_store.js"></script>
<script type="text/javascript" src="../components.js"></script>
<script type="text/javascript" src="../libsignal-protocol.js"></script>
<script type="text/javascript" src="../protobufs.js" data-cover></script>
<script type="text/javascript" src="../storage/user.js" data-cover></script>
<script type="text/javascript" src="../storage/unprocessed.js" data-cover></script>
@@ -36,7 +35,6 @@
<script type="text/javascript" src="helpers_test.js"></script>
<script type="text/javascript" src="storage_test.js"></script>
<script type="text/javascript" src="crypto_test.js"></script>
<script type="text/javascript" src="protocol_wrapper_test.js"></script>
<script type="text/javascript" src="contacts_parser_test.js"></script>
<script type="text/javascript" src="generate_keys_test.js"></script>
<script type="text/javascript" src="websocket-resources_test.js"></script>

View File

@@ -1,14 +1,14 @@
// Copyright 2015-2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
/* global libsignal, textsecure */
/* global textsecure */
describe('MessageReceiver', () => {
const { WebSocket } = window;
const number = '+19999999999';
const uuid = 'AAAAAAAA-BBBB-4CCC-9DDD-EEEEEEEEEEEE';
const deviceId = 1;
const signalingKey = libsignal.crypto.getRandomBytes(32 + 20);
const signalingKey = window.Signal.Crypto.getRandomBytes(32 + 20);
before(() => {
localStorage.clear();
@@ -34,7 +34,7 @@ describe('MessageReceiver', () => {
sourceUuid: uuid,
sourceDevice: deviceId,
timestamp: Date.now(),
content: libsignal.crypto.getRandomBytes(200),
content: window.Signal.Crypto.getRandomBytes(200),
};
const body = new textsecure.protobuf.Envelope(attrs).toArrayBuffer();
@@ -54,8 +54,8 @@ describe('MessageReceiver', () => {
});
const messageReceiver = new textsecure.MessageReceiver(
'oldUsername',
'username',
'oldUsername.2',
'username.2',
'password',
'signalingKey',
{
@@ -77,8 +77,8 @@ describe('MessageReceiver', () => {
mockServer = new MockServer('ws://localhost:8081');
messageReceiver = new textsecure.MessageReceiver(
'oldUsername',
'username',
'oldUsername.3',
'username.3',
'password',
'signalingKey',
{

View File

@@ -1,136 +0,0 @@
// Copyright 2016-2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
/* global libsignal, textsecure */
describe('Protocol Wrapper', function protocolWrapperDescribe() {
const store = textsecure.storage.protocol;
const identifier = '+15559999999';
this.timeout(5000);
before(async function thisNeeded() {
localStorage.clear();
this.identityKeyPair = await libsignal.KeyHelper.generateIdentityKeyPair();
await textsecure.storage.protocol.saveIdentity(
identifier,
this.identityKeyPair.pubKey
);
});
describe('processPreKey', () => {
beforeEach(function thisNeeded() {
const address = new libsignal.SignalProtocolAddress(identifier, 1);
this.builder = new libsignal.SessionBuilder(store, address);
});
it('can process prekeys', async function thisNeeded() {
const signedPreKey = await libsignal.KeyHelper.generateSignedPreKey(
this.identityKeyPair,
123
);
await this.builder.processPreKey({
identityKey: this.identityKeyPair.pubKey,
registrationId: 1,
preKey: {
keyId: 1,
publicKey: this.identityKeyPair.pubKey,
},
signedPreKey: {
keyId: 123,
publicKey: signedPreKey.keyPair.pubKey,
signature: signedPreKey.signature,
},
});
});
it('rejects if the identity key changes', function thisNeeded() {
return this.builder
.processPreKey({
identityKey: textsecure.crypto.getRandomBytes(33),
})
.then(() => {
throw new Error('Allowed to overwrite identity key');
})
.catch(e => {
assert.strictEqual(e.message, 'Identity key changed');
});
});
it('rejects with a bad prekey signature', async function thisNeeded() {
const signedPreKey = await libsignal.KeyHelper.generateSignedPreKey(
this.identityKeyPair,
123
);
const bogusSignature = textsecure.crypto.getRandomBytes(64);
return this.builder
.processPreKey({
identityKey: this.identityKeyPair.pubKey,
signedPreKey: {
keyId: 123,
publicKey: signedPreKey.keyPair.pubKey,
signature: bogusSignature,
},
})
.then(() => {
throw new Error("Didn't reject an invalid signature");
})
.catch(e => {
assert.strictEqual(e.message, 'Signature verification failed');
});
});
it('rejects with a prekey signature for a different identity', async function thisNeeded() {
const bogusSignedPreKey = await libsignal.KeyHelper.generateSignedPreKey(
await libsignal.KeyHelper.generateIdentityKeyPair(),
123
);
return this.builder
.processPreKey({
identityKey: this.identityKeyPair.pubKey,
signedPreKey: {
keyId: 123,
publicKey: bogusSignedPreKey.keyPair.pubKey,
signature: bogusSignedPreKey.signature,
},
})
.then(() => {
throw new Error("Didn't reject an invalid signature");
})
.catch(e => {
assert.strictEqual(e.message, 'Signature verification failed');
});
});
});
describe('cleanOldMessageKeys', () => {
it('should clean old message keys', () => {
const messageKeys = {};
const LIMIT = 2000;
for (let i = 0; i < 2 * LIMIT; i += 1) {
messageKeys[i] = i;
}
libsignal.SessionCipher.cleanOldMessageKeys(messageKeys);
for (let i = 0; i < LIMIT; i += 1) {
assert(
!Object.prototype.hasOwnProperty.call(messageKeys, i),
`should delete old key ${i}`
);
}
for (let i = LIMIT; i < 2 * LIMIT; i += 1) {
assert(
Object.prototype.hasOwnProperty.call(messageKeys, i),
`should have fresh key ${i}`
);
}
});
});
});

View File

@@ -1,18 +1,18 @@
// Copyright 2015-2020 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
/* global libsignal, textsecure, storage, ConversationController */
/* global 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),
pubKey: window.Signal.Crypto.getRandomBytes(33),
privKey: window.Signal.Crypto.getRandomBytes(32),
};
const testKey = {
pubKey: libsignal.crypto.getRandomBytes(33),
privKey: libsignal.crypto.getRandomBytes(32),
pubKey: window.Signal.Crypto.getRandomBytes(33),
privKey: window.Signal.Crypto.getRandomBytes(32),
};
before(async () => {
localStorage.clear();
@@ -40,7 +40,7 @@ describe('SignalProtocolStore', () => {
assertEqualArrayBuffers(key, testKey.pubKey);
});
it('returns whether a key is trusted', async () => {
const newIdentity = libsignal.crypto.getRandomBytes(33);
const newIdentity = window.Signal.Crypto.getRandomBytes(33);
await store.saveIdentity(identifier, testKey.pubKey);
const trusted = await store.isTrustedIdentity(identifier, newIdentity);

View File

@@ -30,7 +30,9 @@ describe('WebSocket-Resource', () => {
assert.strictEqual(request.path, '/some/path');
assertEqualArrayBuffers(
request.body.toArrayBuffer(),
new Uint8Array([1, 2, 3]).buffer
window.Signal.Crypto.typedArrayToArrayBuffer(
new Uint8Array([1, 2, 3])
)
);
request.respond(200, 'OK');
},
@@ -45,7 +47,9 @@ describe('WebSocket-Resource', () => {
id: requestId,
verb: 'PUT',
path: '/some/path',
body: new Uint8Array([1, 2, 3]).buffer,
body: window.Signal.Crypto.typedArrayToArrayBuffer(
new Uint8Array([1, 2, 3])
),
},
})
.encode()
@@ -70,7 +74,9 @@ describe('WebSocket-Resource', () => {
assert.strictEqual(message.request.path, '/some/path');
assertEqualArrayBuffers(
message.request.body.toArrayBuffer(),
new Uint8Array([1, 2, 3]).buffer
window.Signal.Crypto.typedArrayToArrayBuffer(
new Uint8Array([1, 2, 3])
)
);
requestId = message.request.id;
},
@@ -82,7 +88,9 @@ describe('WebSocket-Resource', () => {
resource.sendRequest({
verb: 'PUT',
path: '/some/path',
body: new Uint8Array([1, 2, 3]).buffer,
body: window.Signal.Crypto.typedArrayToArrayBuffer(
new Uint8Array([1, 2, 3])
),
error: done,
success(message, status) {
assert.strictEqual(message, 'OK');