commit
0770871f9c
@ -1,141 +0,0 @@
|
||||
/* global libloki, Multibase, libsignal, StringView, dcodeIO */
|
||||
|
||||
'use strict';
|
||||
|
||||
async function generateSnodeKeysAndAddress() {
|
||||
// snode identitys is a ed25519 keypair
|
||||
const sodium = await window.getSodium();
|
||||
const ed25519KeyPair = sodium.crypto_sign_keypair();
|
||||
const keyPair = {
|
||||
pubKey: ed25519KeyPair.publicKey,
|
||||
privKey: ed25519KeyPair.privateKey,
|
||||
};
|
||||
// snode address is the pubkey in base32z
|
||||
let address = Multibase.encode(
|
||||
'base32z',
|
||||
Multibase.Buffer.from(keyPair.pubKey)
|
||||
).toString();
|
||||
// remove first letter, which is the encoding code
|
||||
address = address.substring(1);
|
||||
return { keyPair, address };
|
||||
}
|
||||
|
||||
describe('Snode Channel', () => {
|
||||
describe('snodeCipher singleton', () => {
|
||||
it('should be defined at libloki.crypto', () => {
|
||||
assert.isDefined(libloki.crypto.snodeCipher);
|
||||
assert.isTrue(
|
||||
libloki.crypto.snodeCipher instanceof libloki.crypto._LokiSnodeChannel
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#decodeSnodeAddressToPubKey', () => {
|
||||
it('should decode a base32z encoded .snode address', async () => {
|
||||
const { keyPair, address } = await generateSnodeKeysAndAddress();
|
||||
|
||||
const buffer = libloki.crypto._decodeSnodeAddressToPubKey(
|
||||
`http://${address}.snode`
|
||||
);
|
||||
|
||||
const expected = new Uint8Array(keyPair.pubKey);
|
||||
assert.strictEqual(expected.length, 32);
|
||||
assert.strictEqual(buffer.length, 32);
|
||||
for (let i = 0; i < buffer.length; i += 1) {
|
||||
assert.strictEqual(buffer[i], expected[i]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('#LokiSnodeChannel', () => {
|
||||
it('should generate an ephemeral key pair', () => {
|
||||
const channel = new libloki.crypto._LokiSnodeChannel();
|
||||
|
||||
assert.isDefined(channel._ephemeralKeyPair);
|
||||
assert.isTrue(channel._ephemeralKeyPair.privKey instanceof ArrayBuffer);
|
||||
assert.isTrue(channel._ephemeralKeyPair.pubKey instanceof ArrayBuffer);
|
||||
const pubKeyHex = StringView.arrayBufferToHex(
|
||||
channel._ephemeralKeyPair.pubKey
|
||||
);
|
||||
assert.strictEqual(channel.getChannelPublicKeyHex(), pubKeyHex);
|
||||
});
|
||||
|
||||
it('should cache something by snode address', async () => {
|
||||
const { address } = await generateSnodeKeysAndAddress();
|
||||
|
||||
const channel = new libloki.crypto._LokiSnodeChannel();
|
||||
// cache should be empty
|
||||
assert.strictEqual(Object.keys(channel._cache).length, 0);
|
||||
|
||||
// push to cache
|
||||
await channel._getSymmetricKey(address);
|
||||
|
||||
assert.strictEqual(Object.keys(channel._cache).length, 1);
|
||||
assert.strictEqual(Object.keys(channel._cache)[0], address);
|
||||
});
|
||||
|
||||
it('should encrypt data correctly', async () => {
|
||||
// message sent by Session
|
||||
const snode = await generateSnodeKeysAndAddress();
|
||||
const messageSent = 'I am Groot';
|
||||
const textEncoder = new TextEncoder();
|
||||
const data = textEncoder.encode(messageSent);
|
||||
|
||||
const channel = new libloki.crypto._LokiSnodeChannel();
|
||||
const encrypted = await channel.encrypt(snode.address, data);
|
||||
|
||||
assert.strictEqual(typeof encrypted, 'string');
|
||||
|
||||
// message received by storage server
|
||||
const senderPubKey = StringView.hexToArrayBuffer(
|
||||
channel.getChannelPublicKeyHex()
|
||||
);
|
||||
const sodium = await window.getSodium();
|
||||
const snodePrivKey = sodium.crypto_sign_ed25519_sk_to_curve25519(
|
||||
snode.keyPair.privKey
|
||||
).buffer;
|
||||
const symmetricKey = libsignal.Curve.calculateAgreement(
|
||||
senderPubKey,
|
||||
snodePrivKey
|
||||
);
|
||||
const encryptedArrayBuffer = dcodeIO.ByteBuffer.wrap(
|
||||
encrypted,
|
||||
'base64'
|
||||
).toArrayBuffer();
|
||||
const decrypted = await libloki.crypto.DHDecrypt(
|
||||
symmetricKey,
|
||||
encryptedArrayBuffer
|
||||
);
|
||||
const textDecoder = new TextDecoder();
|
||||
const messageReceived = textDecoder.decode(decrypted);
|
||||
assert.strictEqual(messageSent, messageReceived);
|
||||
});
|
||||
|
||||
it('should decrypt data correctly', async () => {
|
||||
const channel = new libloki.crypto._LokiSnodeChannel();
|
||||
// message sent by storage server
|
||||
const snode = await generateSnodeKeysAndAddress();
|
||||
const messageSent = 'You are Groot';
|
||||
const textEncoder = new TextEncoder();
|
||||
const data = textEncoder.encode(messageSent);
|
||||
const senderPubKey = StringView.hexToArrayBuffer(
|
||||
channel.getChannelPublicKeyHex()
|
||||
);
|
||||
const sodium = await window.getSodium();
|
||||
const snodePrivKey = sodium.crypto_sign_ed25519_sk_to_curve25519(
|
||||
snode.keyPair.privKey
|
||||
).buffer;
|
||||
const symmetricKey = libsignal.Curve.calculateAgreement(
|
||||
senderPubKey,
|
||||
snodePrivKey
|
||||
);
|
||||
const encrypted = await libloki.crypto.DHEncrypt(symmetricKey, data);
|
||||
const encryptedBase64 = dcodeIO.ByteBuffer.wrap(encrypted).toString(
|
||||
'base64'
|
||||
);
|
||||
// message received by Session
|
||||
const decrypted = await channel.decrypt(snode.address, encryptedBase64);
|
||||
assert.strictEqual(messageSent, decrypted);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue