From ca4e2777ff33109f27a82599c239fda1387f0819 Mon Sep 17 00:00:00 2001 From: morrigan Date: Wed, 20 Nov 2019 13:23:36 +0100 Subject: [PATCH] Address PR comments --- src/{types => @types}/basic.ts | 0 src/@types/it-pair/index.d.ts | 6 ++++ src/@types/libp2p.ts | 24 +++++++++++++ src/crypto.ts | 6 ++-- src/handshake.ts | 36 +++++++++++++++---- src/index.ts | 6 +--- src/noise.ts | 63 ++++++++++++++++++---------------- src/types/libp2p.ts | 60 -------------------------------- src/utils.ts | 4 +-- src/xx.ts | 4 +-- test/index.test.ts | 2 +- tsconfig.json | 3 +- 12 files changed, 104 insertions(+), 110 deletions(-) rename src/{types => @types}/basic.ts (100%) create mode 100644 src/@types/it-pair/index.d.ts create mode 100644 src/@types/libp2p.ts delete mode 100644 src/types/libp2p.ts diff --git a/src/types/basic.ts b/src/@types/basic.ts similarity index 100% rename from src/types/basic.ts rename to src/@types/basic.ts diff --git a/src/@types/it-pair/index.d.ts b/src/@types/it-pair/index.d.ts new file mode 100644 index 0000000..d26477b --- /dev/null +++ b/src/@types/it-pair/index.d.ts @@ -0,0 +1,6 @@ +export type Duplex = [Stream, Stream]; + +type Stream = { + sink(source: Iterable), + source: Object, +} diff --git a/src/@types/libp2p.ts b/src/@types/libp2p.ts new file mode 100644 index 0000000..d1686a7 --- /dev/null +++ b/src/@types/libp2p.ts @@ -0,0 +1,24 @@ +import { bytes, bytes32 } from "./basic"; +import { Duplex } from "it-pair"; + +export interface KeyPair { + publicKey: bytes32, + privateKey: bytes32, +} + +export type PeerId = { + id: string, + privKey: string, + pubKey: string, +}; + +export interface NoiseConnection { + remoteEarlyData?(): bytes, + secureOutbound(localPeer: PeerId, insecure: any, remotePeer: PeerId): Promise, + secureInbound(remotePeer: PeerId, insecure: any): Promise, +} + +export type SecureOutbound = { + conn: Duplex, + remotePeer: PeerId, +} diff --git a/src/crypto.ts b/src/crypto.ts index 8d205a9..fafa8a4 100644 --- a/src/crypto.ts +++ b/src/crypto.ts @@ -1,13 +1,13 @@ -import { Duplex } from "./types/libp2p"; +import { Duplex } from "it-pair"; import { NoiseSession } from "./xx"; // Send encrypted payload from the user to stream -export async function encryptStreams(streams: Duplex, session: NoiseSession) : Promise { +export async function encryptStreams(streams: Duplex, session: NoiseSession) : Promise { } // Decrypt received payload from the stream and pipe to user -export async function decryptStreams(streams: Duplex, session: NoiseSession) : Promise { +export async function decryptStreams(streams: Duplex, session: NoiseSession) : Promise { } diff --git a/src/handshake.ts b/src/handshake.ts index dc4d3ab..f6ed058 100644 --- a/src/handshake.ts +++ b/src/handshake.ts @@ -1,19 +1,43 @@ -import { bytes, bytes32 } from "./types/basic"; +import { bytes, bytes32 } from "./@types/basic"; import { NoiseSession, XXHandshake } from "./xx"; -import { KeyPair } from "./types/libp2p"; +import { KeyPair, PeerId } from "./@types/libp2p"; + +type handshakeType = "XX"; export class Handshake { - static async runXX( - isInitiator: boolean, + private type: handshakeType; + private remotePublicKey: bytes; + private signedPayload: bytes; + private prologue: bytes32; + private staticKeys: KeyPair; + + constructor( + type: handshakeType, remotePublicKey: bytes, prologue: bytes32, signedPayload: bytes, staticKeys: KeyPair, - ) : Promise { + ) { + this.type = type; + this.remotePublicKey = remotePublicKey; + this.signedPayload = signedPayload; + this.prologue = prologue; + this.staticKeys = staticKeys; + } + + async propose(isInitiator: boolean) : Promise { const xx = new XXHandshake(); - const nsInit = await xx.initSession(isInitiator, prologue, staticKeys, remotePublicKey); + const nsInit = await xx.initSession(isInitiator, this.prologue, this.staticKeys, this.remotePublicKey); // TODO: exchange handshake messages and confirm handshake return nsInit; } + + async exchange() : Promise { + + } + + async finish() : Promise { + + } } diff --git a/src/index.ts b/src/index.ts index 3cf64c4..e481514 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1 @@ -import { Noise } from './noise'; - -export { - Noise, -} +export * from "./noise"; diff --git a/src/noise.ts b/src/noise.ts index 1caf533..d53a448 100644 --- a/src/noise.ts +++ b/src/noise.ts @@ -1,14 +1,17 @@ import { x25519 } from 'bcrypto'; import { Buffer } from "buffer"; -import { bytes } from "./types/basic"; -import { InsecureConnection, NoiseConnection, PeerId, SecureConnection, KeyPair } from "./types/libp2p"; +import { bytes } from "./@types/basic"; +import {NoiseConnection, PeerId, KeyPair, SecureOutbound} from "./@types/libp2p"; import { Handshake } from "./handshake"; import { generateKeypair, signPayload } from "./utils"; -import { encryptStreams } from "./crypto"; +import { decryptStreams, encryptStreams } from "./crypto"; +import {Duplex} from "./@types/it-pair"; export class Noise implements NoiseConnection { + public protocol = "/noise"; + private readonly privateKey: bytes; private staticKeys: KeyPair; private earlyData?: bytes; @@ -28,29 +31,38 @@ export class Noise implements NoiseConnection { } } - public protocol() { - return '/noise'; - } - - // encrypt outgoing data to the remote party (handshake as initiator) - public async secureOutbound(connection: InsecureConnection, remotePeer: PeerId) : Promise { - try { - const remotePublicKey = Buffer.from(remotePeer.pubKey); - const session = await this.createSecureConnection(connection, remotePublicKey, true); - } catch (e) { + /** + * Encrypt outgoing data to the remote party (handshake as initiator) + * @param {PeerId} localPeer - PeerId of the receiving peer + * @param connection - streaming iterable duplex that will be encrypted + * @param {PeerId} remotePeer - PeerId of the remote peer. Used to validate the integrity of the remote peer. + * @returns {Promise} + */ + public async secureOutbound(localPeer: PeerId, connection: any, remotePeer: PeerId) : Promise { + const remotePublicKey = Buffer.from(remotePeer.pubKey); + const session = await this.createSecureConnection(connection, remotePublicKey, true); + return { + conn: session, + remotePeer, } } - // decrypt incoming data (handshake as responder) - public async secureInbound(connection: InsecureConnection) : Promise { + /** + * Decrypt incoming data (handshake as responder). + * @param {PeerId} localPeer - PeerId of the receiving peer. + * @param connection - streaming iterable duplex that will be encryption. + * @param {PeerId} remotePeer - optional PeerId of the initiating peer, if known. This may only exist during transport upgrades. + * @returns {Promise} + */ + public async secureInbound(localPeer: PeerId, connection: any, remotePeer?: PeerId) : Promise { } private async createSecureConnection( - connection: InsecureConnection, + connection: Duplex, remotePublicKey: bytes, isInitiator: boolean, - ) : Promise { + ) : Promise { if (!this.staticKeys) { this.staticKeys = await generateKeypair(); } @@ -61,20 +73,11 @@ export class Noise implements NoiseConnection { signedPayload = await signPayload(this.privateKey, payload); } - const prologue = Buffer.from(this.protocol()); - const session = await Handshake.runXX(isInitiator, remotePublicKey, prologue, signedPayload, this.staticKeys); + const prologue = Buffer.from(this.protocol); + const handshake = new Handshake('XX', remotePublicKey, prologue, signedPayload, this.staticKeys) + const session = await handshake.propose(isInitiator); - await encryptStreams(connection.streams(), session); - - return { - ...connection, - initiator: isInitiator, - prologue, - localKey: Buffer.alloc(0), // get libp2p public key, - xxNoiseSession: session, - xxComplete: true, - noiseKeypair: this.staticKeys, - } + return await encryptStreams(connection, session); } diff --git a/src/types/libp2p.ts b/src/types/libp2p.ts deleted file mode 100644 index 3ecb276..0000000 --- a/src/types/libp2p.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { bytes, bytes32 } from "./basic"; -import { NoiseSession } from "../xx"; - -export interface KeyPair { - publicKey: bytes32, - privateKey: bytes32, -} - -export type PeerId = { - id: string, - privKey: string, - pubKey: string, -}; - -type PeerInfo = { - noiseKey: bytes32, - libp2pKey: bytes, -}; - -type ConnectionStats = { - direction: "inbound" | "outbound", - encryption: string, -} - - -// Also seen as Pair -export type Stream = { - sink(source: Iterable), - source: Object, -} - -export type Duplex = [Stream, Stream]; - -export interface InsecureConnection { - localPeer: PeerId, - remotePeer: PeerId, - local: PeerInfo, - remote: PeerInfo, - stats: ConnectionStats, - - streams(): Duplex, - addStream(muxedStream: any) : Stream, -} - -export interface NoiseConnection { - remoteEarlyData?(): bytes, - secureOutbound(insecure: InsecureConnection, remotePeer: PeerId): Promise, - secureInbound(insecure: InsecureConnection): Promise, -} - -export interface SecureConnection { - initiator: boolean, - prologue: bytes32, - localKey: bytes, - - xxNoiseSession: NoiseSession, - xxComplete: boolean, - - noiseKeypair: KeyPair, -} diff --git a/src/utils.ts b/src/utils.ts index c01adb4..83a601b 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,8 +1,8 @@ import { x25519 } from 'bcrypto'; import * as crypto from 'libp2p-crypto'; -import { KeyPair } from "./types/libp2p"; -import { bytes } from "./types/basic"; +import { KeyPair } from "./@types/libp2p"; +import { bytes } from "./@types/basic"; export async function generateKeypair() : Promise { const privateKey = x25519.privateKeyGenerate(); diff --git a/src/xx.ts b/src/xx.ts index 3acde91..e78b182 100644 --- a/src/xx.ts +++ b/src/xx.ts @@ -2,8 +2,8 @@ import { Buffer } from 'buffer'; import { AEAD, x25519, HKDF, SHA256 } from 'bcrypto'; import { BN } from 'bn.js'; -import { bytes32, uint32, uint64, bytes } from './types/basic' -import { KeyPair } from './types/libp2p' +import { bytes32, uint32, uint64, bytes } from './@types/basic' +import { KeyPair } from './@types/libp2p' import { generateKeypair } from './utils'; diff --git a/test/index.test.ts b/test/index.test.ts index 6656a5c..808094f 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -4,7 +4,7 @@ import { Noise } from "../src"; describe("Index", () => { it("should expose class with tag and required functions", () => { const noise = new Noise(Buffer.from("privatekey")); - expect(noise.protocol()).to.equal('/noise'); + expect(noise.protocol).to.equal('/noise'); expect(typeof(noise.secureInbound)).to.equal('function'); expect(typeof(noise.secureOutbound)).to.equal('function'); }) diff --git a/tsconfig.json b/tsconfig.json index fccc322..20d8e0c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,7 +7,8 @@ "noImplicitAny": false, "typeRoots": [ "./node_modules/@types", - "./node_modules/bn.js-typings/index.d.ts" + "./node_modules/bn.js-typings/index.d.ts", + "./src/@types" ] }, "include": [