From 6a1f17a2f6c256f43776f795481eb35e59e828b7 Mon Sep 17 00:00:00 2001 From: Matija Petrunic Date: Fri, 17 Apr 2020 10:35:37 +0200 Subject: [PATCH 1/8] Add early data property to handshake --- src/@types/handshake-interface.ts | 1 + src/handshake-ik.ts | 10 ++++++++++ src/handshake-xx-fallback.ts | 3 +++ src/handshake-xx.ts | 10 ++++++++++ 4 files changed, 24 insertions(+) diff --git a/src/@types/handshake-interface.ts b/src/@types/handshake-interface.ts index 9bd7240..a8de48b 100644 --- a/src/@types/handshake-interface.ts +++ b/src/@types/handshake-interface.ts @@ -5,6 +5,7 @@ import PeerId from "peer-id"; export interface IHandshake { session: NoiseSession; remotePeer: PeerId; + earlyData: Uint8Array; encrypt(plaintext: bytes, session: NoiseSession): bytes; decrypt(ciphertext: bytes, session: NoiseSession): {plaintext: bytes; valid: boolean}; } diff --git a/src/handshake-ik.ts b/src/handshake-ik.ts index 983cf2e..d2675a1 100644 --- a/src/handshake-ik.ts +++ b/src/handshake-ik.ts @@ -15,6 +15,7 @@ export class IKHandshake implements IHandshake { public isInitiator: boolean; public session: NoiseSession; public remotePeer!: PeerId; + public earlyData: Uint8Array; private payload: bytes; private prologue: bytes32; @@ -42,6 +43,7 @@ export class IKHandshake implements IHandshake { } this.ik = handshake || new IK(); this.session = this.ik.initSession(this.isInitiator, this.prologue, this.staticKeypair, remoteStaticKey); + this.earlyData = Buffer.alloc(0) } public async stage0(): Promise { @@ -63,6 +65,7 @@ export class IKHandshake implements IHandshake { const decodedPayload = await decodePayload(plaintext); this.remotePeer = this.remotePeer || await getPeerIdFromPayload(decodedPayload); await verifySignedPayload(this.session.hs.rs, decodedPayload, this.remotePeer); + this.setEarlyData(decodedPayload.data); logger("IK Stage 0 - Responder successfully verified payload!"); } catch (e) { logger("Responder breaking up with IK handshake in stage 0."); @@ -86,6 +89,7 @@ export class IKHandshake implements IHandshake { const decodedPayload = await decodePayload(plaintext); this.remotePeer = this.remotePeer || await getPeerIdFromPayload(decodedPayload); await verifySignedPayload(receivedMessageBuffer.ns.slice(0, 32), decodedPayload, this.remotePeer); + this.setEarlyData(decodedPayload.data); logger("IK Stage 1 - Initiator successfully verified payload!"); } catch (e) { logger("Initiator breaking up with IK handshake in stage 1."); @@ -128,4 +132,10 @@ export class IKHandshake implements IHandshake { return encryption ? session.cs2 : session.cs1; } } + + private setEarlyData(data: Uint8Array|null|undefined): void { + if(data){ + this.earlyData = data; + } + } } diff --git a/src/handshake-xx-fallback.ts b/src/handshake-xx-fallback.ts index 6217bc5..9b29e2b 100644 --- a/src/handshake-xx-fallback.ts +++ b/src/handshake-xx-fallback.ts @@ -66,6 +66,9 @@ export class XXFallbackHandshake extends XXHandshake { const decodedPayload = await decodePayload(plaintext); this.remotePeer = this.remotePeer || await getPeerIdFromPayload(decodedPayload); await verifySignedPayload(this.session.hs.rs, decodedPayload, this.remotePeer); + if(decodedPayload.data){ + this.earlyData = decodedPayload.data; + } } catch (e) { throw new Error(`Error occurred while verifying signed payload from responder: ${e.message}`); } diff --git a/src/handshake-xx.ts b/src/handshake-xx.ts index 41360e5..44baa1f 100644 --- a/src/handshake-xx.ts +++ b/src/handshake-xx.ts @@ -19,6 +19,7 @@ export class XXHandshake implements IHandshake { public isInitiator: boolean; public session: NoiseSession; public remotePeer!: PeerId; + public earlyData: Uint8Array; protected payload: bytes; protected connection: WrappedConnection; @@ -46,6 +47,7 @@ export class XXHandshake implements IHandshake { } this.xx = handshake || new XX(); this.session = this.xx.initSession(this.isInitiator, this.prologue, this.staticKeypair); + this.earlyData = Buffer.alloc(0) } // stage 0 @@ -82,6 +84,7 @@ export class XXHandshake implements IHandshake { const decodedPayload = await decodePayload(plaintext); this.remotePeer = this.remotePeer || await getPeerIdFromPayload(decodedPayload); this.remotePeer = await verifySignedPayload(receivedMessageBuffer.ns, decodedPayload, this.remotePeer); + this.setEarlyData(decodedPayload.data) } catch (e) { throw new Error(`Error occurred while verifying signed payload: ${e.message}`); } @@ -114,6 +117,7 @@ export class XXHandshake implements IHandshake { const decodedPayload = await decodePayload(plaintext); this.remotePeer = this.remotePeer || await getPeerIdFromPayload(decodedPayload); await verifySignedPayload(this.session.hs.rs, decodedPayload, this.remotePeer); + this.setEarlyData(decodedPayload.data) } catch (e) { throw new Error(`Error occurred while verifying signed payload: ${e.message}`); } @@ -146,4 +150,10 @@ export class XXHandshake implements IHandshake { return encryption ? session.cs2 : session.cs1; } } + + private setEarlyData(data: Uint8Array|null|undefined): void { + if(data){ + this.earlyData = data + } + } } From 09c5df3b0dedead5f10103c27917f2c81544b85c Mon Sep 17 00:00:00 2001 From: Matija Petrunic Date: Fri, 17 Apr 2020 10:36:29 +0200 Subject: [PATCH 2/8] Add early data field to connection return --- src/@types/libp2p.ts | 1 + src/noise.ts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/@types/libp2p.ts b/src/@types/libp2p.ts index 151d0ca..588c71d 100644 --- a/src/@types/libp2p.ts +++ b/src/@types/libp2p.ts @@ -14,6 +14,7 @@ export interface INoiseConnection { export type SecureOutbound = { conn: any; + earlyData: Uint8Array; remotePeer: PeerId; } diff --git a/src/noise.ts b/src/noise.ts index 404d9a7..8d93cfb 100644 --- a/src/noise.ts +++ b/src/noise.ts @@ -85,6 +85,7 @@ export class Noise implements INoiseConnection { return { conn, + earlyData: handshake.earlyData, remotePeer: handshake.remotePeer, } } @@ -115,6 +116,7 @@ export class Noise implements INoiseConnection { return { conn, + earlyData: handshake.earlyData, remotePeer: handshake.remotePeer }; } From cb7eee74074bcd88c0317ab532dfb6a9c86b4c0b Mon Sep 17 00:00:00 2001 From: Matija Petrunic Date: Fri, 17 Apr 2020 10:56:31 +0200 Subject: [PATCH 3/8] Convert earlyData to Buffer --- src/@types/handshake-interface.ts | 2 +- src/@types/libp2p.ts | 2 +- src/handshake-ik.ts | 4 ++-- src/handshake-xx-fallback.ts | 6 +++++- src/handshake-xx.ts | 4 ++-- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/@types/handshake-interface.ts b/src/@types/handshake-interface.ts index a8de48b..a2d930a 100644 --- a/src/@types/handshake-interface.ts +++ b/src/@types/handshake-interface.ts @@ -5,7 +5,7 @@ import PeerId from "peer-id"; export interface IHandshake { session: NoiseSession; remotePeer: PeerId; - earlyData: Uint8Array; + earlyData: Buffer; encrypt(plaintext: bytes, session: NoiseSession): bytes; decrypt(ciphertext: bytes, session: NoiseSession): {plaintext: bytes; valid: boolean}; } diff --git a/src/@types/libp2p.ts b/src/@types/libp2p.ts index 588c71d..db29558 100644 --- a/src/@types/libp2p.ts +++ b/src/@types/libp2p.ts @@ -14,7 +14,7 @@ export interface INoiseConnection { export type SecureOutbound = { conn: any; - earlyData: Uint8Array; + earlyData: Buffer; remotePeer: PeerId; } diff --git a/src/handshake-ik.ts b/src/handshake-ik.ts index d2675a1..372319f 100644 --- a/src/handshake-ik.ts +++ b/src/handshake-ik.ts @@ -15,7 +15,7 @@ export class IKHandshake implements IHandshake { public isInitiator: boolean; public session: NoiseSession; public remotePeer!: PeerId; - public earlyData: Uint8Array; + public earlyData: Buffer; private payload: bytes; private prologue: bytes32; @@ -135,7 +135,7 @@ export class IKHandshake implements IHandshake { private setEarlyData(data: Uint8Array|null|undefined): void { if(data){ - this.earlyData = data; + this.earlyData = Buffer.from(data.buffer, data.byteOffset, data.length); } } } diff --git a/src/handshake-xx-fallback.ts b/src/handshake-xx-fallback.ts index 9b29e2b..34647a3 100644 --- a/src/handshake-xx-fallback.ts +++ b/src/handshake-xx-fallback.ts @@ -67,7 +67,11 @@ export class XXFallbackHandshake extends XXHandshake { this.remotePeer = this.remotePeer || await getPeerIdFromPayload(decodedPayload); await verifySignedPayload(this.session.hs.rs, decodedPayload, this.remotePeer); if(decodedPayload.data){ - this.earlyData = decodedPayload.data; + this.earlyData = Buffer.from( + decodedPayload.data.buffer, + decodedPayload.data.byteOffset, + decodedPayload.data.length + ); } } catch (e) { throw new Error(`Error occurred while verifying signed payload from responder: ${e.message}`); diff --git a/src/handshake-xx.ts b/src/handshake-xx.ts index 44baa1f..3f217ac 100644 --- a/src/handshake-xx.ts +++ b/src/handshake-xx.ts @@ -19,7 +19,7 @@ export class XXHandshake implements IHandshake { public isInitiator: boolean; public session: NoiseSession; public remotePeer!: PeerId; - public earlyData: Uint8Array; + public earlyData: Buffer; protected payload: bytes; protected connection: WrappedConnection; @@ -153,7 +153,7 @@ export class XXHandshake implements IHandshake { private setEarlyData(data: Uint8Array|null|undefined): void { if(data){ - this.earlyData = data + this.earlyData = Buffer.from(data.buffer, data.byteOffset, data.length); } } } From 9b650d5b5fb772ff3a65ac706c198eb8d7887fa5 Mon Sep 17 00:00:00 2001 From: Matija Petrunic Date: Fri, 17 Apr 2020 10:56:38 +0200 Subject: [PATCH 4/8] Add test --- test/noise.test.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/noise.test.ts b/test/noise.test.ts index e1ac841..6e493e3 100644 --- a/test/noise.test.ts +++ b/test/noise.test.ts @@ -336,4 +336,30 @@ describe("Noise", () => { assert(false, e.message); } }); + + it("should accept and return early data from remote peer", async() => { + try { + const localPeerEarlyData = Buffer.from('early data') + const staticKeysInitiator = generateKeypair(); + const noiseInit = new Noise(staticKeysInitiator.privateKey, localPeerEarlyData); + const staticKeysResponder = generateKeypair(); + const noiseResp = new Noise(staticKeysResponder.privateKey); + + // Prepare key cache for noise pipes + KeyCache.store(localPeer, staticKeysInitiator.publicKey); + KeyCache.store(remotePeer, staticKeysResponder.publicKey); + + const [inboundConnection, outboundConnection] = DuplexPair(); + const [outbound, inbound] = await Promise.all([ + noiseInit.secureOutbound(localPeer, outboundConnection, remotePeer), + noiseResp.secureInbound(remotePeer, inboundConnection), + ]); + + assert(inbound.earlyData.equals(localPeerEarlyData)) + assert(outbound.earlyData.equals(Buffer.alloc(0))) + } catch (e) { + console.error(e); + assert(false, e.message); + } + }); }); From 7625aa8e46a2cf66c19d024ecf4c02b7138617e4 Mon Sep 17 00:00:00 2001 From: Matija Petrunic Date: Fri, 17 Apr 2020 11:04:50 +0200 Subject: [PATCH 5/8] Rename to remoteEarlyData --- src/@types/handshake-interface.ts | 2 +- src/@types/libp2p.ts | 2 +- src/handshake-ik.ts | 4 ++-- src/handshake-xx-fallback.ts | 2 +- src/handshake-xx.ts | 6 +++--- src/noise.ts | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/@types/handshake-interface.ts b/src/@types/handshake-interface.ts index a2d930a..f432bda 100644 --- a/src/@types/handshake-interface.ts +++ b/src/@types/handshake-interface.ts @@ -5,7 +5,7 @@ import PeerId from "peer-id"; export interface IHandshake { session: NoiseSession; remotePeer: PeerId; - earlyData: Buffer; + remoteEarlyData: Buffer; encrypt(plaintext: bytes, session: NoiseSession): bytes; decrypt(ciphertext: bytes, session: NoiseSession): {plaintext: bytes; valid: boolean}; } diff --git a/src/@types/libp2p.ts b/src/@types/libp2p.ts index db29558..3c02747 100644 --- a/src/@types/libp2p.ts +++ b/src/@types/libp2p.ts @@ -14,7 +14,7 @@ export interface INoiseConnection { export type SecureOutbound = { conn: any; - earlyData: Buffer; + remoteEarlyData: Buffer; remotePeer: PeerId; } diff --git a/src/handshake-ik.ts b/src/handshake-ik.ts index 372319f..9d76f46 100644 --- a/src/handshake-ik.ts +++ b/src/handshake-ik.ts @@ -15,7 +15,7 @@ export class IKHandshake implements IHandshake { public isInitiator: boolean; public session: NoiseSession; public remotePeer!: PeerId; - public earlyData: Buffer; + public remoteEarlyData: Buffer; private payload: bytes; private prologue: bytes32; @@ -43,7 +43,7 @@ export class IKHandshake implements IHandshake { } this.ik = handshake || new IK(); this.session = this.ik.initSession(this.isInitiator, this.prologue, this.staticKeypair, remoteStaticKey); - this.earlyData = Buffer.alloc(0) + this.remoteEarlyData = Buffer.alloc(0) } public async stage0(): Promise { diff --git a/src/handshake-xx-fallback.ts b/src/handshake-xx-fallback.ts index 34647a3..da3f8ce 100644 --- a/src/handshake-xx-fallback.ts +++ b/src/handshake-xx-fallback.ts @@ -67,7 +67,7 @@ export class XXFallbackHandshake extends XXHandshake { this.remotePeer = this.remotePeer || await getPeerIdFromPayload(decodedPayload); await verifySignedPayload(this.session.hs.rs, decodedPayload, this.remotePeer); if(decodedPayload.data){ - this.earlyData = Buffer.from( + this.remoteEarlyData = Buffer.from( decodedPayload.data.buffer, decodedPayload.data.byteOffset, decodedPayload.data.length diff --git a/src/handshake-xx.ts b/src/handshake-xx.ts index 3f217ac..eb91f26 100644 --- a/src/handshake-xx.ts +++ b/src/handshake-xx.ts @@ -19,7 +19,7 @@ export class XXHandshake implements IHandshake { public isInitiator: boolean; public session: NoiseSession; public remotePeer!: PeerId; - public earlyData: Buffer; + public remoteEarlyData: Buffer; protected payload: bytes; protected connection: WrappedConnection; @@ -47,7 +47,7 @@ export class XXHandshake implements IHandshake { } this.xx = handshake || new XX(); this.session = this.xx.initSession(this.isInitiator, this.prologue, this.staticKeypair); - this.earlyData = Buffer.alloc(0) + this.remoteEarlyData = Buffer.alloc(0) } // stage 0 @@ -153,7 +153,7 @@ export class XXHandshake implements IHandshake { private setEarlyData(data: Uint8Array|null|undefined): void { if(data){ - this.earlyData = Buffer.from(data.buffer, data.byteOffset, data.length); + this.remoteEarlyData = Buffer.from(data.buffer, data.byteOffset, data.length); } } } diff --git a/src/noise.ts b/src/noise.ts index 8d93cfb..214721c 100644 --- a/src/noise.ts +++ b/src/noise.ts @@ -116,7 +116,7 @@ export class Noise implements INoiseConnection { return { conn, - earlyData: handshake.earlyData, + remoteEarlyData: handshake.remoteEarlyData, remotePeer: handshake.remotePeer }; } From 93d6a9a99b6e321697a71a33b9afbf189eef730e Mon Sep 17 00:00:00 2001 From: Matija Petrunic Date: Fri, 17 Apr 2020 11:07:58 +0200 Subject: [PATCH 6/8] Fix test --- src/handshake-ik.ts | 2 +- src/noise.ts | 2 +- test/noise.test.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/handshake-ik.ts b/src/handshake-ik.ts index 9d76f46..b52de0c 100644 --- a/src/handshake-ik.ts +++ b/src/handshake-ik.ts @@ -135,7 +135,7 @@ export class IKHandshake implements IHandshake { private setEarlyData(data: Uint8Array|null|undefined): void { if(data){ - this.earlyData = Buffer.from(data.buffer, data.byteOffset, data.length); + this.remoteEarlyData = Buffer.from(data.buffer, data.byteOffset, data.length); } } } diff --git a/src/noise.ts b/src/noise.ts index 214721c..777b3e0 100644 --- a/src/noise.ts +++ b/src/noise.ts @@ -85,7 +85,7 @@ export class Noise implements INoiseConnection { return { conn, - earlyData: handshake.earlyData, + remoteEarlyData: handshake.remoteEarlyData, remotePeer: handshake.remotePeer, } } diff --git a/test/noise.test.ts b/test/noise.test.ts index 6e493e3..7130eac 100644 --- a/test/noise.test.ts +++ b/test/noise.test.ts @@ -355,8 +355,8 @@ describe("Noise", () => { noiseResp.secureInbound(remotePeer, inboundConnection), ]); - assert(inbound.earlyData.equals(localPeerEarlyData)) - assert(outbound.earlyData.equals(Buffer.alloc(0))) + assert(inbound.remoteEarlyData.equals(localPeerEarlyData)) + assert(outbound.remoteEarlyData.equals(Buffer.alloc(0))) } catch (e) { console.error(e); assert(false, e.message); From 01a4388fa227bd3658a19d57ab608fccaec5d45c Mon Sep 17 00:00:00 2001 From: Matija Petrunic Date: Fri, 17 Apr 2020 11:09:46 +0200 Subject: [PATCH 7/8] Rename function --- src/handshake-ik.ts | 6 +++--- src/handshake-xx.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/handshake-ik.ts b/src/handshake-ik.ts index b52de0c..ddf1de4 100644 --- a/src/handshake-ik.ts +++ b/src/handshake-ik.ts @@ -65,7 +65,7 @@ export class IKHandshake implements IHandshake { const decodedPayload = await decodePayload(plaintext); this.remotePeer = this.remotePeer || await getPeerIdFromPayload(decodedPayload); await verifySignedPayload(this.session.hs.rs, decodedPayload, this.remotePeer); - this.setEarlyData(decodedPayload.data); + this.setRemoteEarlyData(decodedPayload.data); logger("IK Stage 0 - Responder successfully verified payload!"); } catch (e) { logger("Responder breaking up with IK handshake in stage 0."); @@ -89,7 +89,7 @@ export class IKHandshake implements IHandshake { const decodedPayload = await decodePayload(plaintext); this.remotePeer = this.remotePeer || await getPeerIdFromPayload(decodedPayload); await verifySignedPayload(receivedMessageBuffer.ns.slice(0, 32), decodedPayload, this.remotePeer); - this.setEarlyData(decodedPayload.data); + this.setRemoteEarlyData(decodedPayload.data); logger("IK Stage 1 - Initiator successfully verified payload!"); } catch (e) { logger("Initiator breaking up with IK handshake in stage 1."); @@ -133,7 +133,7 @@ export class IKHandshake implements IHandshake { } } - private setEarlyData(data: Uint8Array|null|undefined): void { + private setRemoteEarlyData(data: Uint8Array|null|undefined): void { if(data){ this.remoteEarlyData = Buffer.from(data.buffer, data.byteOffset, data.length); } diff --git a/src/handshake-xx.ts b/src/handshake-xx.ts index eb91f26..bb2b849 100644 --- a/src/handshake-xx.ts +++ b/src/handshake-xx.ts @@ -84,7 +84,7 @@ export class XXHandshake implements IHandshake { const decodedPayload = await decodePayload(plaintext); this.remotePeer = this.remotePeer || await getPeerIdFromPayload(decodedPayload); this.remotePeer = await verifySignedPayload(receivedMessageBuffer.ns, decodedPayload, this.remotePeer); - this.setEarlyData(decodedPayload.data) + this.setRemoteEarlyData(decodedPayload.data) } catch (e) { throw new Error(`Error occurred while verifying signed payload: ${e.message}`); } @@ -117,7 +117,7 @@ export class XXHandshake implements IHandshake { const decodedPayload = await decodePayload(plaintext); this.remotePeer = this.remotePeer || await getPeerIdFromPayload(decodedPayload); await verifySignedPayload(this.session.hs.rs, decodedPayload, this.remotePeer); - this.setEarlyData(decodedPayload.data) + this.setRemoteEarlyData(decodedPayload.data) } catch (e) { throw new Error(`Error occurred while verifying signed payload: ${e.message}`); } @@ -151,7 +151,7 @@ export class XXHandshake implements IHandshake { } } - private setEarlyData(data: Uint8Array|null|undefined): void { + private setRemoteEarlyData(data: Uint8Array|null|undefined): void { if(data){ this.remoteEarlyData = Buffer.from(data.buffer, data.byteOffset, data.length); } From 7c62ef4b47c4c41e3e70df2e2e809b7907ba4e89 Mon Sep 17 00:00:00 2001 From: Matija Petrunic Date: Fri, 17 Apr 2020 11:14:27 +0200 Subject: [PATCH 8/8] Reuse super method --- src/handshake-xx-fallback.ts | 8 +------- src/handshake-xx.ts | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/handshake-xx-fallback.ts b/src/handshake-xx-fallback.ts index da3f8ce..fd66546 100644 --- a/src/handshake-xx-fallback.ts +++ b/src/handshake-xx-fallback.ts @@ -66,13 +66,7 @@ export class XXFallbackHandshake extends XXHandshake { const decodedPayload = await decodePayload(plaintext); this.remotePeer = this.remotePeer || await getPeerIdFromPayload(decodedPayload); await verifySignedPayload(this.session.hs.rs, decodedPayload, this.remotePeer); - if(decodedPayload.data){ - this.remoteEarlyData = Buffer.from( - decodedPayload.data.buffer, - decodedPayload.data.byteOffset, - decodedPayload.data.length - ); - } + this.setRemoteEarlyData(decodedPayload.data) } catch (e) { throw new Error(`Error occurred while verifying signed payload from responder: ${e.message}`); } diff --git a/src/handshake-xx.ts b/src/handshake-xx.ts index bb2b849..17bece8 100644 --- a/src/handshake-xx.ts +++ b/src/handshake-xx.ts @@ -151,7 +151,7 @@ export class XXHandshake implements IHandshake { } } - private setRemoteEarlyData(data: Uint8Array|null|undefined): void { + protected setRemoteEarlyData(data: Uint8Array|null|undefined): void { if(data){ this.remoteEarlyData = Buffer.from(data.buffer, data.byteOffset, data.length); }