diff --git a/package.json b/package.json index a9e9400..391ece7 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "eslint": "^6.6.0", "libp2p-crypto": "^0.17.1", "mocha": "^6.2.2", + "peer-id": "^0.13.5", "typescript": "^3.6.4" }, "babel": { diff --git a/src/noise.ts b/src/noise.ts index b3be2df..d216446 100644 --- a/src/noise.ts +++ b/src/noise.ts @@ -25,7 +25,7 @@ export class Noise implements NoiseConnection { constructor(privateKey: bytes, staticNoiseKey?: bytes, earlyData?: bytes) { this.privateKey = privateKey; - this.earlyData = earlyData; + this.earlyData = earlyData || Buffer.alloc(0); if (staticNoiseKey) { const publicKey = x25519.publicKeyCreate(staticNoiseKey); @@ -83,10 +83,14 @@ export class Noise implements NoiseConnection { const prologue = Buffer.from(this.protocol); const handshake = new Handshake('XX', isInitiator, remotePublicKey, prologue, this.staticKeys, connection); + console.log("Starting with handshake in createSecureConnection") + const session = await handshake.propose(this.earlyData); await handshake.exchange(session); await handshake.finish(session); + console.log("Finished handshake in createSecureConnection") + // Create encryption box/unbox wrapper const [secure, user] = DuplexPair(); const network = connection.unwrap(); diff --git a/test/fixtures/peer.ts b/test/fixtures/peer.ts index e69de29..431e4b6 100644 --- a/test/fixtures/peer.ts +++ b/test/fixtures/peer.ts @@ -0,0 +1,36 @@ +import PeerId from 'peer-id'; + +// ed25519 keys +const peers = [{ + id: '12D3KooWH45PiqBjfnEfDfCD6TqJrpqTBJvQDwGHvjGpaWwms46D', + privKey: 'CAESYBtKXrMwawAARmLScynQUuSwi/gGSkwqDPxi15N3dqDHa4T4iWupkMe5oYGwGH3Hyfvd/QcgSTqg71oYZJadJ6prhPiJa6mQx7mhgbAYfcfJ+939ByBJOqDvWhhklp0nqg==', + pubKey: 'CAESIGuE+IlrqZDHuaGBsBh9x8n73f0HIEk6oO9aGGSWnSeq' +}, { + id: '12D3KooWP63uzL78BRMpkQ7augMdNi1h3VBrVWZucKjyhzGVaSi1', + privKey: 'CAESYPxO3SHyfc2578hDmfkGGBY255JjiLuVavJWy+9ivlpsxSyVKf36ipyRGL6szGzHuFs5ceEuuGVrPMg/rW2Ch1bFLJUp/fqKnJEYvqzMbMe4Wzlx4S64ZWs8yD+tbYKHVg==', + pubKey: 'CAESIMUslSn9+oqckRi+rMxsx7hbOXHhLrhlazzIP61tgodW' +}, { + id: '12D3KooWF85R7CM2Wikdtb2sjwnd24e1tgojf3MEWwizmVB8PA6U', + privKey: 'CAESYNXoQ5CnooE939AEqE2JJGPqvhoFJn0xP+j9KwjfOfDkTtPyfn2kJ1gn3uOYTcmoHFU1bbETNtRVuPMi1fmDmqFO0/J+faQnWCfe45hNyagcVTVtsRM21FW48yLV+YOaoQ==', + pubKey: 'CAESIE7T8n59pCdYJ97jmE3JqBxVNW2xEzbUVbjzItX5g5qh' +}, { + id: '12D3KooWPCofiCjhdtezP4eMnqBjjutFZNHjV39F5LWNrCvaLnzT', + privKey: 'CAESYLhUut01XPu+yIPbtZ3WnxOd26FYuTMRn/BbdFYsZE2KxueKRlo9yIAxmFReoNFUKztUU4G2aUiTbqDQaA6i0MDG54pGWj3IgDGYVF6g0VQrO1RTgbZpSJNuoNBoDqLQwA==', + pubKey: 'CAESIMbnikZaPciAMZhUXqDRVCs7VFOBtmlIk26g0GgOotDA' +}]; + +export async function createPeerIdsFromFixtures (length) { + return Promise.all( + Array.from({ length }).map((_, i) => PeerId.createFromJSON(peers[i])) + ) +} + +export async function createPeerIds (length) { + const peerIds: any[] = []; + for (let i = 0; i < length; i++) { + const id = await PeerId.create({ keyType: 'ed25519'}); + peerIds.push(id); + } + + return peerIds; +} diff --git a/test/noise.test.ts b/test/noise.test.ts index 240b0be..3542388 100644 --- a/test/noise.test.ts +++ b/test/noise.test.ts @@ -2,13 +2,54 @@ import { expect } from "chai"; import DuplexPair from 'it-pair/duplex'; import { Noise } from "../src"; -import {generateEd25519Keys} from "./utils"; +import { generateEd25519Keys } from "./utils"; +import {createPeerIds, createPeerIdsFromFixtures} from "./fixtures/peer"; +import Wrap from "it-pb-rpc"; +import {Handshake} from "../src/handshake"; +import { + createHandshakePayload, + decodeMessageBuffer, + encodeMessageBuffer, + generateKeypair, + getHandshakePayload, + signPayload +} from "../src/utils"; +import {XXHandshake} from "../src/xx"; +import {Buffer} from "buffer"; describe("Noise", () => { - it("should encrypt outgoing data using secureOutbound", async() => { - // const libp2pKeys = await generateEd25519Keys(); - // - // const noise = new Noise(libp2pKeys._key); - // await noise.secureOutbound(); + let remotePeer, localPeer; + + before(async () => { + [remotePeer, localPeer] = await createPeerIds(2); + }); + + it("should test that secureOutbound is spec compliant", async() => { + const libp2pKeys = await generateEd25519Keys(); + + const noise = new Noise(libp2pKeys._key); + + const [inboundConnection, outboundConnection] = DuplexPair(); + await Promise.all([ + noise.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 handshake = new Handshake('XX', false, localPeer.pubKey.bytes, prologue, staticKeys, wrapped); + + // Finish handshake + console.log("Starting with handshake as responder in test..."); + const sessionResponder = await handshake.propose(Buffer.alloc(0)); + await handshake.exchange(sessionResponder); + await handshake.finish(sessionResponder); + console.log("Finished handshake as responder in test..."); + + // Create the encrypted streams + })(), + ]); }) }); diff --git a/yarn.lock b/yarn.lock index 803cd19..63ec7c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1103,6 +1103,13 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= +base-x@3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.4.tgz#94c1788736da065edb1d68808869e357c977fa77" + integrity sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA== + dependencies: + safe-buffer "^5.0.1" + base-x@^3.0.2: version "3.0.7" resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.7.tgz#1c5a7fafe8f66b4114063e8da102799d4e7c408f" @@ -1361,6 +1368,16 @@ chownr@^1.1.1: resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== +cids@~0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/cids/-/cids-0.7.1.tgz#d8bba49a35a0e82110879b5001abf1039c62347f" + integrity sha512-qEM4j2GKE/BiT6WdUi6cfW8dairhSLTUE8tIdxJG6SvY33Mp/UPjw+xcO0n1zsllgo72BupzKF/44v+Bg8YPPg== + dependencies: + class-is "^1.1.0" + multibase "~0.6.0" + multicodec "~0.5.1" + multihashes "~0.4.14" + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" @@ -1369,6 +1386,11 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: inherits "^2.0.1" safe-buffer "^5.0.1" +class-is@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" + integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== + class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -2586,7 +2608,7 @@ libp2p-crypto-secp256k1@~0.4.0: safe-buffer "^5.1.2" secp256k1 "^3.6.2" -libp2p-crypto@^0.17.1: +libp2p-crypto@^0.17.1, libp2p-crypto@~0.17.0: version "0.17.1" resolved "https://registry.yarnpkg.com/libp2p-crypto/-/libp2p-crypto-0.17.1.tgz#20da30d133930e589d9b68057859c65ae677a7cf" integrity sha512-IPz/rn8OtHY1Lae2teowSLw6UMqjkL0eM1fVOdPWRrB8fobDfPuwp67E3v7xGtarf6JSYpugsqTj89KEgbcBtw== @@ -2804,7 +2826,21 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -multihashes@~0.4.13, multihashes@~0.4.15: +multibase@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.0.tgz#0216e350614c7456da5e8e5b20d3fcd4c9104f56" + integrity sha512-R9bNLQhbD7MsitPm1NeY7w9sDgu6d7cuj25snAWH7k5PSNPSwIQQBpcpj8jx1W96dLbdigZqmUWOdQRMnAmgjA== + dependencies: + base-x "3.0.4" + +multicodec@~0.5.1: + version "0.5.5" + resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-0.5.5.tgz#55c2535b44eca9ea40a13771420153fe075bb36d" + integrity sha512-1kOifvwAqp9IdiiTKmpK2tS+LY6GHZdKpk3S2EvW4T32vlwDyA3hJoZtGauzqdedUPVNGChnTksEotVOCVlC+Q== + dependencies: + varint "^5.0.0" + +multihashes@~0.4.13, multihashes@~0.4.14, multihashes@~0.4.15: version "0.4.15" resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.15.tgz#6dbc55f7f312c6782f5367c03c9783681589d8a6" integrity sha512-G/Smj1GWqw1RQP3dRuRRPe3oyLqvPqUaEDIaoi7JF7Loxl4WAWvhJNk84oyDEodSucv0MmSW/ZT0RKUrsIFD3g== @@ -3171,6 +3207,17 @@ pathval@^1.1.0: resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA= +peer-id@^0.13.5: + version "0.13.5" + resolved "https://registry.yarnpkg.com/peer-id/-/peer-id-0.13.5.tgz#1a0fd8e11a6b62be1304830ca52abe89fd151898" + integrity sha512-vDdiP4Qb6yiKD2cKyJqEdL08gL+/847Rbl8qBm+Q7mcrsbzzMzwQ5IBQ2yUeb0um71V5ny5/JqH83wFXv6wSmg== + dependencies: + cids "~0.7.1" + class-is "^1.1.0" + libp2p-crypto "~0.17.0" + multihashes "~0.4.15" + protons "^1.0.1" + pem-jwk@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/pem-jwk/-/pem-jwk-2.0.0.tgz#1c5bb264612fc391340907f5c1de60c06d22f085"