From a8ff05cdf18d17f0998a8977aac685238337830d Mon Sep 17 00:00:00 2001 From: morrigan Date: Thu, 28 Nov 2019 17:32:46 +0100 Subject: [PATCH] Update handling keys, refactoring --- src/@types/libp2p.ts | 4 +-- src/handshake.ts | 69 +++++++++++++++++++----------------- src/noise.ts | 43 ++++++++++++++--------- src/utils.ts | 43 ++++++++++++++--------- src/xx.ts | 21 +++++------ test/handshake.test.ts | 33 +++++++++++++----- test/noise.test.ts | 53 ++++++++++------------------ test/xx.test.ts | 79 ++++++++++++++++++++++++++---------------- 8 files changed, 194 insertions(+), 151 deletions(-) diff --git a/src/@types/libp2p.ts b/src/@types/libp2p.ts index 1698dfe..2c3323f 100644 --- a/src/@types/libp2p.ts +++ b/src/@types/libp2p.ts @@ -9,10 +9,10 @@ export interface KeyPair { export type PeerId = { id: bytes, privKey: { - bytes: bytes, + marshal(): bytes, }, pubKey: { - bytes: bytes, + marshal(): bytes, }, }; diff --git a/src/handshake.ts b/src/handshake.ts index 29581ac..6342512 100644 --- a/src/handshake.ts +++ b/src/handshake.ts @@ -8,93 +8,98 @@ import { decodeMessageBuffer, encodeMessageBuffer, getHandshakePayload, - logger, + logger, signEarlyDataPayload, signPayload, } from "./utils"; import { WrappedConnection } from "./noise"; -type handshakeType = "XX"; - export class Handshake { public isInitiator: boolean; + public session: NoiseSession; - private type: handshakeType; - private remotePublicKey: bytes; + private remotePublicKey?: bytes; + private libp2pPrivateKey: bytes; + private libp2pPublicKey: bytes; private prologue: bytes32; private staticKeys: KeyPair; private connection: WrappedConnection; private xx: XXHandshake; constructor( - type: handshakeType, isInitiator: boolean, - remotePublicKey: bytes, + libp2pPrivateKey: bytes, + libp2pPublicKey: bytes, prologue: bytes32, staticKeys: KeyPair, connection: WrappedConnection, handshake?: XXHandshake, ) { - this.type = type; this.isInitiator = isInitiator; - this.remotePublicKey = remotePublicKey; + this.libp2pPrivateKey = libp2pPrivateKey; + this.libp2pPublicKey = libp2pPublicKey; this.prologue = prologue; this.staticKeys = staticKeys; this.connection = connection; this.xx = handshake || new XXHandshake(); + this.session = this.xx.initSession(this.isInitiator, this.prologue, this.staticKeys); } // stage 0 - async propose(earlyData?: bytes) : Promise { - const ns = await this.xx.initSession(this.isInitiator, this.prologue, this.staticKeys, this.remotePublicKey); - + async propose(earlyData?: bytes) : Promise { if (this.isInitiator) { - const signedPayload = signPayload(this.staticKeys.privateKey, getHandshakePayload(this.staticKeys.publicKey)); + const signedPayload = signPayload(this.libp2pPrivateKey, getHandshakePayload(this.staticKeys.publicKey)); + const signedEarlyDataPayload = signEarlyDataPayload(this.libp2pPrivateKey, earlyData || Buffer.alloc(0)); const handshakePayload = await createHandshakePayload( - this.staticKeys.publicKey, + this.libp2pPublicKey, + this.libp2pPrivateKey, signedPayload, - earlyData, - this.staticKeys.privateKey + signedEarlyDataPayload ); - const messageBuffer = await this.xx.sendMessage(ns, handshakePayload); + const messageBuffer = await this.xx.sendMessage(this.session, handshakePayload); this.connection.writeLP(encodeMessageBuffer(messageBuffer)); - logger("Stage 0 - Initiator finished proposing"); + logger("Stage 0 - Initiator finished proposing, sent signed NoiseHandshake payload."); } else { - const receivedMessageBuffer = (await this.connection.readLP()).slice(); - const plaintext = await this.xx.recvMessage(ns, decodeMessageBuffer(receivedMessageBuffer)); - logger("Stage 0 - Responder received proposed message."); - } + const receivedMessageBuffer = decodeMessageBuffer((await this.connection.readLP()).slice()); + this.remotePublicKey = receivedMessageBuffer.ne; - return ns; + const plaintext = await this.xx.recvMessage(this.session, receivedMessageBuffer); + logger("Stage 0 - Responder received proposed message and remote static public key."); + } } // stage 1 - async exchange(session: NoiseSession) : Promise { + async exchange() : Promise { if (this.isInitiator) { - const receivedMessageBuffer = (await this.connection.readLP()).slice(); - const plaintext = await this.xx.recvMessage(session, decodeMessageBuffer(receivedMessageBuffer)); + const receivedMessageBuffer = decodeMessageBuffer((await this.connection.readLP()).slice()); + this.remotePublicKey = receivedMessageBuffer.ne; + const plaintext = await this.xx.recvMessage(this.session, receivedMessageBuffer); logger('Stage 1 - Initiator received the message.'); } else { // create payload as responder - const signedPayload = signPayload(this.staticKeys.privateKey, getHandshakePayload(this.staticKeys.publicKey)); - const handshakePayload = await createHandshakePayload(this.remotePublicKey, signedPayload); + const signedPayload = signPayload(this.libp2pPrivateKey, getHandshakePayload(this.staticKeys.publicKey)); + const handshakePayload = await createHandshakePayload( + this.libp2pPublicKey, + this.libp2pPrivateKey, + signedPayload, + ); - const messageBuffer = await this.xx.sendMessage(session, handshakePayload); + const messageBuffer = await this.xx.sendMessage(this.session, handshakePayload); this.connection.writeLP(encodeMessageBuffer(messageBuffer)); logger('Stage 1 - Responder sent the message.') } } // stage 2 - async finish(session: NoiseSession) : Promise { + async finish() : Promise { if (this.isInitiator) { - const messageBuffer = await this.xx.sendMessage(session, Buffer.alloc(0)); + const messageBuffer = await this.xx.sendMessage(this.session, Buffer.alloc(0)); this.connection.writeLP(encodeMessageBuffer(messageBuffer)); logger('Stage 2 - Initiator sent message.'); } else { const receivedMessageBuffer = (await this.connection.readLP()).slice(); - const plaintext = await this.xx.recvMessage(session, decodeMessageBuffer(receivedMessageBuffer)); + const plaintext = await this.xx.recvMessage(this.session, decodeMessageBuffer(receivedMessageBuffer)); logger('Stage 2 - Responder received the message, finished handshake.') } } diff --git a/src/noise.ts b/src/noise.ts index 2795c4c..4e783fc 100644 --- a/src/noise.ts +++ b/src/noise.ts @@ -12,6 +12,7 @@ import { decryptStream, encryptStream } from "./crypto"; import { bytes } from "./@types/basic"; import { NoiseConnection, PeerId, KeyPair, SecureOutbound } from "./@types/libp2p"; import { Duplex } from "./@types/it-pair"; +import {NoiseSession} from "./xx"; export type WrappedConnection = ReturnType; @@ -27,7 +28,7 @@ export class Noise implements NoiseConnection { this.earlyData = earlyData || Buffer.alloc(0); if (staticNoiseKey) { - const publicKey = x25519.publicKeyCreate(staticNoiseKey); + const publicKey = x25519.publicKeyCreate(staticNoiseKey); // TODO: verify this this.staticKeys = { privateKey: staticNoiseKey, publicKey, @@ -46,8 +47,9 @@ export class Noise implements NoiseConnection { */ public async secureOutbound(localPeer: PeerId, connection: any, remotePeer: PeerId) : Promise { const wrappedConnection = Wrap(connection); - const remotePublicKey = remotePeer.pubKey.bytes; - const conn = await this.createSecureConnection(wrappedConnection, remotePublicKey, true); + const libp2pPublicKey = localPeer.pubKey.marshal(); + const handshake = await this.performHandshake(wrappedConnection, true, libp2pPublicKey); + const conn = await this.createSecureConnection(wrappedConnection, handshake); return { conn, @@ -64,8 +66,9 @@ export class Noise implements NoiseConnection { */ public async secureInbound(localPeer: PeerId, connection: any, remotePeer: PeerId) : Promise { const wrappedConnection = Wrap(connection); - const remotePublicKey = remotePeer.pubKey.bytes; - const conn = await this.createSecureConnection(wrappedConnection, remotePublicKey, false); + const libp2pPublicKey = localPeer.pubKey.marshal(); + const handshake = await this.performHandshake(wrappedConnection, false, libp2pPublicKey); + const conn = await this.createSecureConnection(wrappedConnection, handshake); return { conn, @@ -73,19 +76,25 @@ export class Noise implements NoiseConnection { }; } + private async performHandshake( + connection: WrappedConnection, + isInitiator: boolean, + libp2pPublicKey: bytes, + ): Promise { + const prologue = Buffer.from(this.protocol); + const handshake = new Handshake(isInitiator, this.privateKey, libp2pPublicKey, prologue, this.staticKeys, connection); + + await handshake.propose(this.earlyData); + await handshake.exchange(); + await handshake.finish(); + + return handshake; + } + private async createSecureConnection( connection: WrappedConnection, - remotePublicKey: bytes, - isInitiator: boolean, + handshake: Handshake, ) : Promise { - // Perform handshake - const prologue = Buffer.from(this.protocol); - const handshake = new Handshake('XX', isInitiator, remotePublicKey, prologue, this.staticKeys, connection); - - const session = await handshake.propose(this.earlyData); - await handshake.exchange(session); - await handshake.finish(session); - // Create encryption box/unbox wrapper const [secure, user] = DuplexPair(); const network = connection.unwrap(); @@ -93,12 +102,12 @@ export class Noise implements NoiseConnection { pipe( secure, // write to wrapper ensureBuffer, // ensure any type of data is converted to buffer - encryptStream(handshake, session), // data is encrypted + encryptStream(handshake, handshake.session), // data is encrypted lp.encode({ lengthEncoder: int16BEEncode }), // prefix with message length network, // send to the remote peer lp.decode({ lengthDecoder: int16BEDecode }), // read message length prefix ensureBuffer, // ensure any type of data is converted to buffer - decryptStream(handshake, session), // decrypt the incoming data + decryptStream(handshake, handshake.session), // decrypt the incoming data secure // pipe to the wrapper ); diff --git a/src/utils.ts b/src/utils.ts index f87609e..1be87f3 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -26,42 +26,50 @@ export function generateKeypair() : KeyPair { export async function createHandshakePayload( libp2pPublicKey: bytes, + libp2pPrivateKey: bytes, signedPayload: bytes, - earlyData?: bytes, - libp2pPrivateKey?: bytes, + signedEarlyData?: EarlyDataPayload, ) : Promise { const NoiseHandshakePayload = await loadPayloadProto(); + const earlyDataPayload = signedEarlyData ? + { + libp2pData: signedEarlyData.libp2pData, + libp2pDataSignature: signedEarlyData.libp2pDataSignature, + } : {}; + const payloadInit = NoiseHandshakePayload.create({ libp2pKey: libp2pPublicKey, noiseStaticKeySignature: signedPayload, - ...resolveEarlyDataPayload(libp2pPrivateKey, earlyData), + ...earlyDataPayload, }); return Buffer.from(NoiseHandshakePayload.encode(payloadInit).finish()); } -export function signPayload(privateKey: bytes, payload: bytes) { - return ed25519.sign(payload, privateKey); +export function signPayload(libp2pPrivateKey: bytes, payload: bytes) { + return ed25519.sign(payload, libp2pPrivateKey); } -export const getHandshakePayload = (publicKey: bytes ) => Buffer.concat([Buffer.from("noise-libp2p-static-key:"), publicKey]); - -export const getEarlyDataPayload = (earlyData: bytes) => Buffer.concat([Buffer.from("noise-libp2p-early-data:"), earlyData]); - -function resolveEarlyDataPayload(privateKey?: bytes, earlyData?: bytes) : Object { - if (!earlyData || !privateKey) { - return {}; - } +type EarlyDataPayload = { + libp2pData: bytes; + libp2pDataSignature: bytes; +} +export function signEarlyDataPayload(libp2pPrivateKey: bytes, earlyData: bytes) : EarlyDataPayload { const payload = getEarlyDataPayload(earlyData); - const signedPayload = signPayload(privateKey, payload); + const signedPayload = signPayload(libp2pPrivateKey, payload); + return { libp2pData: payload, libp2pDataSignature: signedPayload, } } +export const getHandshakePayload = (publicKey: bytes ) => Buffer.concat([Buffer.from("noise-libp2p-static-key:"), publicKey]); + +export const getEarlyDataPayload = (earlyData: bytes) => Buffer.concat([Buffer.from("noise-libp2p-early-data:"), earlyData]); + export function encodeMessageBuffer(message: MessageBuffer) : bytes { return Buffer.concat([message.ne, message.ns, message.ciphertext]); } @@ -69,8 +77,8 @@ export function encodeMessageBuffer(message: MessageBuffer) : bytes { export function decodeMessageBuffer(message: bytes) : MessageBuffer { return { ne: message.slice(0, 32), - ns: message.slice(32, 80), - ciphertext: message.slice(80, message.length), + ns: message.slice(32, 64), + ciphertext: message.slice(64, message.length), } } @@ -82,5 +90,6 @@ int16BEEncode.bytes = 2; export const int16BEDecode = data => { if (data.length < 2) throw RangeError('Could not decode int16BE'); - return data.readInt16BE(0);} + return data.readInt16BE(0); +}; int16BEDecode.bytes = 2; diff --git a/src/xx.ts b/src/xx.ts index 851013f..a82524e 100644 --- a/src/xx.ts +++ b/src/xx.ts @@ -50,18 +50,18 @@ export class XXHandshake { return Buffer.alloc(32); } - private async initializeInitiator(prologue: bytes32, s: KeyPair, rs: bytes32, psk: bytes32): Promise { + private initializeInitiator(prologue: bytes32, s: KeyPair, rs: bytes32, psk: bytes32): HandshakeState { const name = "Noise_XX_25519_ChaChaPoly_SHA256"; - const ss = await this.initializeSymmetric(name); + const ss = this.initializeSymmetric(name); this.mixHash(ss, prologue); const re = Buffer.alloc(32); return { ss, s, rs, psk, re }; } - private async initializeResponder(prologue: bytes32, s: KeyPair, rs: bytes32, psk: bytes32): Promise { + private initializeResponder(prologue: bytes32, s: KeyPair, rs: bytes32, psk: bytes32): HandshakeState { const name = "Noise_XX_25519_ChaChaPoly_SHA256"; - const ss = await this.initializeSymmetric(name); + const ss = this.initializeSymmetric(name); this.mixHash(ss, prologue); const re = Buffer.alloc(32); @@ -145,9 +145,9 @@ export class XXHandshake { // Symmetric state related - private async initializeSymmetric(protocolName: string): Promise { + private initializeSymmetric(protocolName: string): SymmetricState { const protocolNameBytes: bytes = Buffer.from(protocolName, 'utf-8'); - const h = await this.hashProtocolName(protocolNameBytes); + const h = this.hashProtocolName(protocolNameBytes); const ck = h; const key = this.createEmptyKey(); @@ -162,7 +162,7 @@ export class XXHandshake { ss.ck = ck; } - private async hashProtocolName(protocolName: bytes): Promise { + private hashProtocolName(protocolName: bytes): bytes32 { if (protocolName.length <= 32) { const h = Buffer.alloc(32); protocolName.copy(h); @@ -319,14 +319,15 @@ export class XXHandshake { return this.decryptWithAd(cs, Buffer.alloc(0), message.ciphertext); } - public async initSession(initiator: boolean, prologue: bytes32, s: KeyPair, rs: bytes32): Promise { + public initSession(initiator: boolean, prologue: bytes32, s: KeyPair): NoiseSession { const psk = this.createEmptyKey(); + const rs = Buffer.alloc(32); // no static key yet let hs; if (initiator) { - hs = await this.initializeInitiator(prologue, s, rs, psk); + hs = this.initializeInitiator(prologue, s, rs, psk); } else { - hs = await this.initializeResponder(prologue, s, rs, psk); + hs = this.initializeResponder(prologue, s, rs, psk); } return { diff --git a/test/handshake.test.ts b/test/handshake.test.ts index faba67a..033d392 100644 --- a/test/handshake.test.ts +++ b/test/handshake.test.ts @@ -5,6 +5,8 @@ import Wrap from "it-pb-rpc"; import {Handshake} from "../src/handshake"; import {generateKeypair} from "../src/utils"; +import {createPeerIds, createPeerIdsFromFixtures} from "./fixtures/peer"; + describe("Handshake", () => { it("should propose, exchange and finish handshake", async() => { @@ -15,24 +17,39 @@ describe("Handshake", () => { const prologue = Buffer.from('/noise'); const staticKeysInitiator = generateKeypair(); const staticKeysResponder = generateKeypair(); + const [peerA, peerB] = await createPeerIds(2); - const handshakeInitator = new Handshake('XX', true, staticKeysResponder.publicKey, prologue, staticKeysInitiator, connectionFrom); - const handshakeResponder = new Handshake('XX', false, staticKeysInitiator.publicKey, prologue, staticKeysResponder, connectionTo); + const initiatorPrivKey = peerA.privKey.marshal().slice(0, 32); + const initiatorPubKey = peerA.pubKey.marshal(); + const handshakeInitator = new Handshake(true, initiatorPrivKey, initiatorPubKey, prologue, staticKeysInitiator, connectionFrom); - const sessionInitator = await handshakeInitator.propose(); - const sessionResponder = await handshakeResponder.propose(); + const responderPrivKey = peerB.privKey.marshal().slice(0, 32); + const responderPubKey = peerB.pubKey.marshal(); + const handshakeResponder = new Handshake(false, responderPrivKey, responderPubKey, prologue, staticKeysResponder, connectionTo); - await handshakeResponder.exchange(sessionResponder); - await handshakeInitator.exchange(sessionInitator); + await handshakeInitator.propose(); + await handshakeResponder.propose(); - await handshakeInitator.finish(sessionInitator); - await handshakeResponder.finish( sessionResponder); + await handshakeResponder.exchange(); + await handshakeInitator.exchange(); + await handshakeInitator.finish(); + await handshakeResponder.finish(); + + const sessionInitator = handshakeInitator.session; + const sessionResponder = handshakeResponder.session; + + // Test shared key if (sessionInitator.cs1 && sessionResponder.cs1 && sessionInitator.cs2 && sessionResponder.cs2) { assert(sessionInitator.cs1.k.equals(sessionResponder.cs1.k)); assert(sessionInitator.cs2.k.equals(sessionResponder.cs2.k)); } else { assert(false); } + + // Test encryption and decryption + const encrypted = handshakeInitator.encrypt(Buffer.from("encryptthis"), handshakeInitator.session); + const decrypted = handshakeResponder.decrypt(encrypted, handshakeResponder.session); + assert(decrypted.equals(Buffer.from("encryptthis"))); }); }); diff --git a/test/noise.test.ts b/test/noise.test.ts index 25eaa98..22f5578 100644 --- a/test/noise.test.ts +++ b/test/noise.test.ts @@ -21,29 +21,15 @@ describe("Noise", () => { let remotePeer, localPeer; before(async () => { - // [remotePeer, localPeer] = await createPeerIds(2); - // TODO: Handle Peer ID received ed25519 keys - - const pair1 = generateKeypair(); - remotePeer = { - id: "id-1", - pubKey: { bytes: pair1.publicKey }, - privKey: { bytes: pair1.privateKey }, - } - const pair2 = generateKeypair(); - localPeer = { - id: "id-2", - pubKey: { bytes: pair2.publicKey }, - privKey: { bytes: pair2.privateKey }, - } + [localPeer, remotePeer] = await createPeerIds(2); }); it("should communicate through encrypted streams", async() => { - const libp2pKeys = await generateEd25519Keys(); - const libp2pKeys2 = await generateEd25519Keys(); + const libp2pInitPrivKey = localPeer.privKey.marshal().slice(0, 32); + const libp2pRespPrivKey = remotePeer.privKey.marshal().slice(0, 32); - const noiseInit = new Noise(libp2pKeys._key, localPeer.privKey.bytes); - const noiseResp = new Noise(libp2pKeys2._key, remotePeer.privKey.bytes); + const noiseInit = new Noise(libp2pInitPrivKey); + const noiseResp = new Noise(libp2pRespPrivKey); const [inboundConnection, outboundConnection] = DuplexPair(); const [outbound, inbound] = await Promise.all([ @@ -59,39 +45,36 @@ describe("Noise", () => { }); it("should test that secureOutbound is spec compliant", async() => { - const libp2pKeys = await generateEd25519Keys(); - const noiseInit = new Noise(libp2pKeys._key, localPeer.privKey.bytes); + const libp2pPrivKey = localPeer.privKey.marshal().slice(0, 32); + const noiseInit = new Noise(libp2pPrivKey); const [inboundConnection, outboundConnection] = DuplexPair(); - const [outbound, { wrapped, ns, handshake }] = await Promise.all([ + const [outbound, { wrapped, handshake }] = await Promise.all([ noiseInit.secureOutbound(localPeer, outboundConnection, remotePeer), (async () => { const wrapped = Wrap(inboundConnection); const prologue = Buffer.from('/noise'); - const staticKeys = { - privateKey: remotePeer.privKey.bytes, - publicKey: remotePeer.pubKey.bytes, - }; + const staticKeys = generateKeypair(); const xx = new XXHandshake(); - const handshake = new Handshake('XX', false, localPeer.pubKey.bytes, prologue, staticKeys, wrapped, xx); - const ns = await xx.initSession(false, prologue, staticKeys, localPeer.pubKey.bytes); + const libp2pPubKey = remotePeer.pubKey.marshal().slice(32, 64); + const handshake = new Handshake(false, libp2pPrivKey, libp2pPubKey, prologue, staticKeys, wrapped, xx); let receivedMessageBuffer = decodeMessageBuffer((await wrapped.readLP()).slice()); // The first handshake message contains the initiator's ephemeral public key expect(receivedMessageBuffer.ne.length).equal(32); - await xx.recvMessage(ns, receivedMessageBuffer); + await xx.recvMessage(handshake.session, receivedMessageBuffer); // Stage 1 - const signedPayload = signPayload(staticKeys.privateKey, getHandshakePayload(staticKeys.publicKey)); - const handshakePayload = await createHandshakePayload(localPeer.pubKey.bytes, signedPayload); + const signedPayload = signPayload(libp2pPrivKey, getHandshakePayload(staticKeys.publicKey)); + const handshakePayload = await createHandshakePayload(libp2pPubKey, libp2pPrivKey, signedPayload); - const messageBuffer = await xx.sendMessage(ns, handshakePayload); + const messageBuffer = await xx.sendMessage(handshake.session, handshakePayload); wrapped.writeLP(encodeMessageBuffer(messageBuffer)); // Stage 2 - finish handshake receivedMessageBuffer = decodeMessageBuffer((await wrapped.readLP()).slice()); - await xx.recvMessage(ns, receivedMessageBuffer); - return { wrapped, ns, handshake }; + await xx.recvMessage(handshake.session, receivedMessageBuffer); + return { wrapped, handshake }; })(), ]); @@ -102,7 +85,7 @@ describe("Noise", () => { const receivedEncryptedPayload = (await wrapped.read()).slice(); const dataLength = receivedEncryptedPayload.readInt16BE(0); const data = receivedEncryptedPayload.slice(2, dataLength + 2); - const decrypted = handshake.decrypt(data, ns); + const decrypted = handshake.decrypt(data, handshake.session); // Decrypted data should match assert(decrypted.equals(Buffer.from("test"))); }) diff --git a/test/xx.test.ts b/test/xx.test.ts index afd7f9d..9ff5c6b 100644 --- a/test/xx.test.ts +++ b/test/xx.test.ts @@ -10,13 +10,16 @@ describe("Index", () => { const prologue = Buffer.from("/noise", "utf-8"); it("Test creating new XX session", async () => { - const xx = new XXHandshake(); + try { + const xx = new XXHandshake(); - const kpInitiator: KeyPair = await generateKeypair(); - const kpResponder: KeyPair = await generateKeypair(); + const kpInitiator: KeyPair = await generateKeypair(); + const kpResponder: KeyPair = await generateKeypair(); - - const session = await xx.initSession(true, prologue, kpInitiator, kpResponder.publicKey); + const session = await xx.initSession(true, prologue, kpInitiator); + } catch (e) { + assert(false, e.message); + } }); it("Test get HKDF", async () => { @@ -45,14 +48,16 @@ describe("Index", () => { const respSignedPayload = await libp2pRespKeys.sign(getHandshakePayload(kpResp.publicKey)); // initiator: new XX noise session - const nsInit = await xx.initSession(true, prologue, kpInit, kpResp.publicKey); + const nsInit = await xx.initSession(true, prologue, kpInit); // responder: new XX noise session - const nsResp = await xx.initSession(false, prologue, kpResp, kpInit.publicKey); + const nsResp = await xx.initSession(false, prologue, kpResp); /* STAGE 0 */ // initiator creates payload - const payloadInitEnc = await createHandshakePayload(libp2pInitKeys.bytes, initSignedPayload) + const libp2pInitPrivKey = libp2pInitKeys.marshal().slice(0, 32); + const libp2pInitPubKey = libp2pInitKeys.marshal().slice(32, 64); + const payloadInitEnc = await createHandshakePayload(libp2pInitPubKey, libp2pInitPrivKey, initSignedPayload); // initiator sends message const message = Buffer.concat([Buffer.alloc(0), payloadInitEnc]); @@ -67,7 +72,9 @@ describe("Index", () => { /* STAGE 1 */ // responder creates payload - const payloadRespEnc = await createHandshakePayload(libp2pRespKeys.bytes, respSignedPayload); + const libp2pRespPrivKey = libp2pRespKeys.marshal().slice(0, 32); + const libp2pRespPubKey = libp2pRespKeys.marshal().slice(32, 64); + const payloadRespEnc = await createHandshakePayload(libp2pRespPubKey, libp2pRespPrivKey, respSignedPayload); const message1 = Buffer.concat([message, payloadRespEnc]); const messageBuffer2 = await xx.sendMessage(nsResp, message1); @@ -95,36 +102,48 @@ describe("Index", () => { } it("Test handshake", async () => { - const xx = new XXHandshake(); - await doHandshake(xx); + try { + const xx = new XXHandshake(); + await doHandshake(xx); + } catch (e) { + assert(false, e.message); + } }); 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"); + try { + 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); - assert(!Buffer.from("HelloCrypto").equals(message), "Encrypted message should not be same as plaintext."); - const decrypted = xx.decryptWithAd(nsResp.cs1, ad, message); + xx.encryptWithAd(nsInit.cs1, ad, message); + assert(!Buffer.from("HelloCrypto").equals(message), "Encrypted message should not be same as plaintext."); + const decrypted = xx.decryptWithAd(nsResp.cs1, ad, message); - assert(Buffer.from("HelloCrypto").equals(decrypted), "Decrypted text not equal to original message."); + assert(Buffer.from("HelloCrypto").equals(decrypted), "Decrypted text not equal to original message."); + } catch (e) { + assert(false, e.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"); + try { + 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."); + 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."); + 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."); + } catch (e) { + assert(false, e.message); + } }); });