From 06d5034998a801796ef452628d6aa331c4b9b10f Mon Sep 17 00:00:00 2001 From: morrigan Date: Sat, 8 Feb 2020 12:23:35 +0100 Subject: [PATCH] Update setting remote id --- src/handshake-ik.ts | 5 ++--- src/handshake-xx-fallback.ts | 3 +-- src/handshake-xx.ts | 6 ++---- src/utils.ts | 19 +++++++++++++++++-- test/noise.test.ts | 31 +++++++++++++++++++++++++++++++ 5 files changed, 53 insertions(+), 11 deletions(-) diff --git a/src/handshake-ik.ts b/src/handshake-ik.ts index 92a1cbd..22938d4 100644 --- a/src/handshake-ik.ts +++ b/src/handshake-ik.ts @@ -56,9 +56,8 @@ export class IKHandshake implements IHandshake { try { const receivedMessageBuffer = decode1(receivedMsg); const plaintext = this.ik.recvMessage(this.session, receivedMessageBuffer); - this.remotePeer = await getPeerIdFromPayload(plaintext); logger("IK Stage 0 - Responder got message, going to verify payload."); - await verifySignedPayload(receivedMessageBuffer.ns, plaintext, this.remotePeer.id); + this.remotePeer = await verifySignedPayload(receivedMessageBuffer.ns, plaintext, this.remotePeer); logger("IK Stage 0 - Responder successfully verified payload!"); } catch (e) { logger("Responder breaking up with IK handshake in stage 0."); @@ -77,7 +76,7 @@ export class IKHandshake implements IHandshake { logger("IK Stage 1 - Initiator got message, going to verify payload."); try { - await verifySignedPayload(receivedMessageBuffer.ns, plaintext, this.remotePeer.id); + await verifySignedPayload(receivedMessageBuffer.ns, plaintext, this.remotePeer); logger("IK Stage 1 - Initiator successfully verified payload!"); } catch (e) { logger("Initiator breaking up with IK handshake in stage 1."); diff --git a/src/handshake-xx-fallback.ts b/src/handshake-xx-fallback.ts index 21f8272..790873a 100644 --- a/src/handshake-xx-fallback.ts +++ b/src/handshake-xx-fallback.ts @@ -57,8 +57,7 @@ export class XXFallbackHandshake extends XXHandshake { logger("Initiator going to check remote's signature..."); try { - this.remotePeer = await getPeerIdFromPayload(plaintext); - await verifySignedPayload(receivedMessageBuffer.ns, plaintext, this.remotePeer.id); + this.remotePeer = await verifySignedPayload(receivedMessageBuffer.ns, plaintext, this.remotePeer); } 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 8dba492..3b6ce1c 100644 --- a/src/handshake-xx.ts +++ b/src/handshake-xx.ts @@ -72,8 +72,7 @@ export class XXHandshake implements IHandshake { logger("Initiator going to check remote's signature..."); try { - this.remotePeer = await getPeerIdFromPayload(plaintext); - await verifySignedPayload(receivedMessageBuffer.ns, plaintext, this.remotePeer.id); + this.remotePeer = await verifySignedPayload(receivedMessageBuffer.ns, plaintext, this.remotePeer); } catch (e) { throw new Error(`Error occurred while verifying signed payload: ${e.message}`); } @@ -97,11 +96,10 @@ export class XXHandshake implements IHandshake { logger('Stage 2 - Responder waiting for third handshake message...'); const receivedMessageBuffer = decode1(await this.connection.readLP()); const plaintext = this.xx.recvMessage(this.session, receivedMessageBuffer); - this.remotePeer = await getPeerIdFromPayload(plaintext); logger('Stage 2 - Responder received the message, finished handshake. Got remote\'s static key.'); try { - await verifySignedPayload(receivedMessageBuffer.ns, plaintext, this.remotePeer.id); + this.remotePeer = await verifySignedPayload(receivedMessageBuffer.ns, plaintext, this.remotePeer); } catch (e) { throw new Error(`Error occurred while verifying signed payload: ${e.message}`); } diff --git a/src/utils.ts b/src/utils.ts index 8b27f15..ee15f19 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -82,7 +82,18 @@ async function isValidPeerId(peerId: bytes, publicKeyProtobuf: bytes) { return generatedPeerId.id.equals(peerId); } -export async function verifySignedPayload(noiseStaticKey: bytes, plaintext: bytes, peerId: bytes) { +/** + * Verifies signed payload and returns peer id that has sent the payload. + * @param {bytes} noiseStaticKey - owner's noise static key + * @param {bytes} plaintext - encoded payload + * @param {PeerId} remotePeer - (optional) owner's libp2p peer ID + * @returns {Promise} - peer ID of payload owner + */ +export async function verifySignedPayload( + noiseStaticKey: bytes, + plaintext: bytes, + remotePeer?: PeerId +): Promise { let receivedPayload; try { const NoiseHandshakePayload = await loadPayloadProto(); @@ -97,7 +108,9 @@ export async function verifySignedPayload(noiseStaticKey: bytes, plaintext: byte throw new Error("Failed to decode received payload. Reason: " + e.message); } - if (!(await isValidPeerId(peerId, receivedPayload.identityKey)) ) { + remotePeer = remotePeer || await getPeerIdFromPayload(plaintext); + + if (!(await isValidPeerId(remotePeer.id, receivedPayload.identityKey)) ) { throw new Error("Peer ID doesn't match libp2p public key."); } @@ -108,6 +121,8 @@ export async function verifySignedPayload(noiseStaticKey: bytes, plaintext: byte if (!publicKey.verify(generatedPayload, receivedPayload.identitySig)) { throw new Error("Static key doesn't match to peer that signed payload!"); } + + return remotePeer; } export function getHkdf(ck: bytes32, ikm: bytes): Hkdf { diff --git a/test/noise.test.ts b/test/noise.test.ts index b15a338..eadf0d5 100644 --- a/test/noise.test.ts +++ b/test/noise.test.ts @@ -300,4 +300,35 @@ describe("Noise", () => { assert(false, e.message); } }); + + it("should working without remote peer provided in incoming connection", async() => { + try { + const staticKeysInitiator = generateKeypair(); + const noiseInit = new Noise(staticKeysInitiator.privateKey); + 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), + ]); + const wrappedInbound = Wrap(inbound.conn); + const wrappedOutbound = Wrap(outbound.conn); + + wrappedOutbound.writeLP(Buffer.from("test v2")); + const response = await wrappedInbound.readLP(); + expect(response.toString()).equal("test v2"); + + assert(inbound.remotePeer.marshalPubKey().equals(localPeer.marshalPubKey())); + assert(outbound.remotePeer.marshalPubKey().equals(remotePeer.marshalPubKey())); + } catch (e) { + console.error(e); + assert(false, e.message); + } + }); });