2019-11-06 13:24:30 +01:00
|
|
|
import { expect, assert } from "chai";
|
2019-11-04 17:06:31 +01:00
|
|
|
import { Buffer } from 'buffer';
|
|
|
|
|
2019-11-20 20:03:33 +01:00
|
|
|
import { XXHandshake } from "../src/xx";
|
|
|
|
import { KeyPair } from "../src/@types/libp2p";
|
2019-11-20 21:38:14 +01:00
|
|
|
import { generateEd25519Keys } from "./utils";
|
|
|
|
import {createHandshakePayload, generateKeypair, getHandshakePayload} from "../src/utils";
|
2019-11-04 17:06:31 +01:00
|
|
|
|
|
|
|
describe("Index", () => {
|
|
|
|
const prologue = Buffer.from("/noise", "utf-8");
|
|
|
|
|
|
|
|
it("Test creating new XX session", async () => {
|
|
|
|
const xx = new XXHandshake();
|
|
|
|
|
2019-11-20 20:03:33 +01:00
|
|
|
const kpInitiator: KeyPair = await generateKeypair();
|
|
|
|
const kpResponder: KeyPair = await generateKeypair();
|
2019-11-04 21:34:12 +01:00
|
|
|
|
|
|
|
|
2019-11-04 17:06:31 +01:00
|
|
|
const session = await xx.initSession(true, prologue, kpInitiator, kpResponder.publicKey);
|
2019-11-20 20:03:33 +01:00
|
|
|
});
|
2019-11-05 13:25:03 +01:00
|
|
|
|
|
|
|
it("Test get HKDF", async () => {
|
|
|
|
const xx = new XXHandshake();
|
|
|
|
const ckBytes = Buffer.from('4e6f6973655f58585f32353531395f58436861436861506f6c795f53484132353600000000000000000000000000000000000000000000000000000000000000', 'hex');
|
|
|
|
const ikm = Buffer.from('a3eae50ea37a47e8a7aa0c7cd8e16528670536dcd538cebfd724fb68ce44f1910ad898860666227d4e8dd50d22a9a64d1c0a6f47ace092510161e9e442953da3', 'hex');
|
|
|
|
const ck = Buffer.alloc(32);
|
|
|
|
ckBytes.copy(ck);
|
|
|
|
|
|
|
|
const [k1, k2, k3] = xx.getHkdf(ck, ikm);
|
|
|
|
expect(k1.toString('hex')).to.equal('cc5659adff12714982f806e2477a8d5ddd071def4c29bb38777b7e37046f6914');
|
|
|
|
expect(k2.toString('hex')).to.equal('a16ada915e551ab623f38be674bb4ef15d428ae9d80688899c9ef9b62ef208fa');
|
|
|
|
expect(k3.toString('hex')).to.equal('ff67bf9727e31b06efc203907e6786667d2c7a74ac412b4d31a80ba3fd766f68');
|
2019-11-20 20:03:33 +01:00
|
|
|
});
|
2019-11-06 13:24:30 +01:00
|
|
|
|
2019-11-06 16:09:15 +01:00
|
|
|
async function doHandshake(xx) {
|
2019-11-21 14:43:12 +01:00
|
|
|
const kpInit = await generateKeypair();
|
|
|
|
const kpResp = await generateKeypair();
|
2019-11-06 13:24:30 +01:00
|
|
|
|
|
|
|
// initiator setup
|
2019-11-06 15:16:13 +01:00
|
|
|
const libp2pInitKeys = await generateEd25519Keys();
|
2019-11-20 21:38:14 +01:00
|
|
|
const initSignedPayload = await libp2pInitKeys.sign(getHandshakePayload(kpInit.publicKey));
|
2019-11-06 13:24:30 +01:00
|
|
|
|
|
|
|
// responder setup
|
2019-11-06 15:16:13 +01:00
|
|
|
const libp2pRespKeys = await generateEd25519Keys();
|
2019-11-20 21:38:14 +01:00
|
|
|
const respSignedPayload = await libp2pRespKeys.sign(getHandshakePayload(kpResp.publicKey));
|
2019-11-06 13:24:30 +01:00
|
|
|
|
|
|
|
// initiator: new XX noise session
|
|
|
|
const nsInit = await xx.initSession(true, prologue, kpInit, kpResp.publicKey);
|
|
|
|
// responder: new XX noise session
|
|
|
|
const nsResp = await xx.initSession(false, prologue, kpResp, kpInit.publicKey);
|
|
|
|
|
2019-11-06 15:16:13 +01:00
|
|
|
/* STAGE 0 */
|
2019-11-06 13:24:30 +01:00
|
|
|
|
|
|
|
// initiator creates payload
|
2019-11-20 21:38:14 +01:00
|
|
|
const payloadInitEnc = await createHandshakePayload(libp2pInitKeys.bytes, initSignedPayload)
|
2019-11-06 13:24:30 +01:00
|
|
|
|
|
|
|
// initiator sends message
|
|
|
|
const message = Buffer.concat([Buffer.alloc(0), payloadInitEnc]);
|
|
|
|
const messageBuffer = await xx.sendMessage(nsInit, message);
|
|
|
|
|
|
|
|
expect(messageBuffer.ne.length).not.equal(0);
|
2019-11-06 15:16:13 +01:00
|
|
|
|
|
|
|
// responder receives message
|
2019-11-06 15:49:20 +01:00
|
|
|
const plaintext = await xx.recvMessage(nsResp, messageBuffer);
|
|
|
|
console.log("Stage 0 responder payload: ", plaintext);
|
2019-11-06 15:16:13 +01:00
|
|
|
|
|
|
|
/* STAGE 1 */
|
|
|
|
|
|
|
|
// responder creates payload
|
2019-11-20 21:38:14 +01:00
|
|
|
const payloadRespEnc = await createHandshakePayload(libp2pRespKeys.bytes, respSignedPayload);
|
2019-11-06 15:16:13 +01:00
|
|
|
|
|
|
|
const message1 = Buffer.concat([message, payloadRespEnc]);
|
|
|
|
const messageBuffer2 = await xx.sendMessage(nsResp, message1);
|
|
|
|
|
|
|
|
expect(messageBuffer2.ne.length).not.equal(0);
|
|
|
|
expect(messageBuffer2.ns.length).not.equal(0);
|
2019-11-06 15:45:28 +01:00
|
|
|
|
|
|
|
// initiator receive payload
|
2019-11-06 15:49:20 +01:00
|
|
|
const plaintext2 = await xx.recvMessage(nsInit, messageBuffer2);
|
|
|
|
console.log("Stage 1 responder payload: ", plaintext2);
|
|
|
|
|
|
|
|
/* STAGE 2 */
|
|
|
|
|
|
|
|
// initiator send message
|
|
|
|
const messageBuffer3 = await xx.sendMessage(nsInit, Buffer.alloc(0));
|
2019-11-06 16:09:15 +01:00
|
|
|
|
2019-11-06 15:49:20 +01:00
|
|
|
// responder receive message
|
|
|
|
const plaintext3 = await xx.recvMessage(nsResp, messageBuffer3);
|
|
|
|
console.log("Stage 2 responder payload: ", plaintext3);
|
|
|
|
|
2019-11-06 16:09:15 +01:00
|
|
|
assert(nsInit.cs1.k.equals(nsResp.cs1.k));
|
|
|
|
assert(nsInit.cs2.k.equals(nsResp.cs2.k));
|
|
|
|
|
2019-11-06 15:49:20 +01:00
|
|
|
return { nsInit, nsResp };
|
2019-11-06 13:24:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
it("Test handshake", async () => {
|
2019-11-06 16:09:15 +01:00
|
|
|
const xx = new XXHandshake();
|
|
|
|
await doHandshake(xx);
|
|
|
|
});
|
2019-11-07 10:55:18 +01:00
|
|
|
|
2019-11-07 17:11:02 +01:00
|
|
|
it("Test symmetric encrypt and decrypt", async () => {
|
|
|
|
const xx = new XXHandshake();
|
|
|
|
const { nsInit, nsResp } = await doHandshake(xx);
|
|
|
|
const ad = Buffer.from("authenticated");
|
|
|
|
const message = Buffer.from("HelloCrypto");
|
|
|
|
|
|
|
|
xx.encryptWithAd(nsInit.cs1, ad, message);
|
2019-11-07 17:19:35 +01:00
|
|
|
assert(!Buffer.from("HelloCrypto").equals(message), "Encrypted message should not be same as plaintext.");
|
2019-11-07 17:11:02 +01:00
|
|
|
const decrypted = xx.decryptWithAd(nsResp.cs1, ad, message);
|
|
|
|
|
2019-11-07 17:19:35 +01:00
|
|
|
assert(Buffer.from("HelloCrypto").equals(decrypted), "Decrypted text not equal to original message.");
|
|
|
|
});
|
|
|
|
|
|
|
|
it("Test multiple messages encryption and decryption", async () => {
|
|
|
|
const xx = new XXHandshake();
|
|
|
|
const { nsInit, nsResp } = await doHandshake(xx);
|
|
|
|
const ad = Buffer.from("authenticated");
|
|
|
|
const message = Buffer.from("ethereum1");
|
|
|
|
|
|
|
|
xx.encryptWithAd(nsInit.cs1, ad, message);
|
|
|
|
const decrypted = xx.decryptWithAd(nsResp.cs1, ad, message);
|
|
|
|
assert(Buffer.from("ethereum1").equals(decrypted), "Decrypted text not equal to original message.");
|
|
|
|
|
|
|
|
const message2 = Buffer.from("ethereum2");
|
|
|
|
xx.encryptWithAd(nsInit.cs1, ad, message2);
|
|
|
|
const decrypted2 = xx.decryptWithAd(nsResp.cs1, ad, message2);
|
|
|
|
assert(Buffer.from("ethereum2").equals(decrypted2), "Decrypted text not equal to original message.");
|
2019-11-07 17:11:02 +01:00
|
|
|
});
|
2019-11-04 17:06:31 +01:00
|
|
|
});
|