diff --git a/src/@types/handshake-interface.ts b/src/@types/handshake-interface.ts new file mode 100644 index 0000000..5c152e5 --- /dev/null +++ b/src/@types/handshake-interface.ts @@ -0,0 +1,8 @@ +import {bytes} from "./basic"; +import {NoiseSession} from "./handshake"; + +export interface HandshakeInterface { + session: NoiseSession; + encrypt(plaintext: bytes, session: NoiseSession): bytes; + decrypt(ciphertext: bytes, session: NoiseSession): bytes; +} diff --git a/src/crypto.ts b/src/crypto.ts index 7ae4733..eff1494 100644 --- a/src/crypto.ts +++ b/src/crypto.ts @@ -1,5 +1,5 @@ import { Buffer } from "buffer"; -import { Handshake } from "./handshake-xx"; +import {HandshakeInterface} from "./@types/handshake-interface"; interface ReturnEncryptionWrapper { (source: Iterable): AsyncIterableIterator; @@ -8,7 +8,7 @@ interface ReturnEncryptionWrapper { const maxPlaintextLength = 65519; // Returns generator that encrypts payload from the user -export function encryptStream(handshake: Handshake): ReturnEncryptionWrapper { +export function encryptStream(handshake: HandshakeInterface): ReturnEncryptionWrapper { return async function * (source) { for await (const chunk of source) { const chunkBuffer = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.length); @@ -28,7 +28,7 @@ export function encryptStream(handshake: Handshake): ReturnEncryptionWrapper { // Decrypt received payload to the user -export function decryptStream(handshake: Handshake): ReturnEncryptionWrapper { +export function decryptStream(handshake: HandshakeInterface): ReturnEncryptionWrapper { return async function * (source) { for await (const chunk of source) { const chunkBuffer = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.length); diff --git a/src/handshake-ik.ts b/src/handshake-ik.ts index b38a5ee..da001bc 100644 --- a/src/handshake-ik.ts +++ b/src/handshake-ik.ts @@ -4,7 +4,7 @@ import {KeyPair, PeerId} from "./@types/libp2p"; import {WrappedConnection} from "./noise"; import {IKHandshake} from "./handshakes/ik"; -export class Handshake { +export class Handshake { // implements HandshakeHandler public isInitiator: boolean; public session: NoiseSession; diff --git a/src/handshake-xx.ts b/src/handshake-xx.ts index b2d96dc..3500077 100644 --- a/src/handshake-xx.ts +++ b/src/handshake-xx.ts @@ -4,6 +4,7 @@ import { XXHandshake } from "./handshakes/xx"; import { KeyPair, PeerId } from "./@types/libp2p"; import { bytes, bytes32 } from "./@types/basic"; import { NoiseSession } from "./@types/handshake"; +import {HandshakeInterface} from "./@types/handshake-interface"; import { createHandshakePayload, getHandshakePayload, @@ -15,7 +16,7 @@ import { logger } from "./logger"; import { decodeMessageBuffer, encodeMessageBuffer } from "./encoder"; import { WrappedConnection } from "./noise"; -export class Handshake { +export class Handshake implements HandshakeInterface { public isInitiator: boolean; public session: NoiseSession; @@ -50,7 +51,7 @@ export class Handshake { } // stage 0 - async propose(): Promise { + public async propose(): Promise { if (this.isInitiator) { logger("Stage 0 - Initiator starting to send first message."); const messageBuffer = this.xx.sendMessage(this.session, Buffer.alloc(0)); @@ -65,7 +66,7 @@ export class Handshake { } // stage 1 - async exchange(): Promise { + public async exchange(): Promise { if (this.isInitiator) { logger('Stage 1 - Initiator waiting to receive first message from responder...'); const receivedMessageBuffer = decodeMessageBuffer((await this.connection.readLP()).slice()); @@ -97,7 +98,7 @@ export class Handshake { } // stage 2 - async finish(earlyData?: bytes): Promise { + public async finish(earlyData?: bytes): Promise { if (this.isInitiator) { logger('Stage 2 - Initiator sending third handshake message.'); const signedPayload = signPayload(this.libp2pPrivateKey, getHandshakePayload(this.staticKeys.publicKey)); diff --git a/src/noise.ts b/src/noise.ts index 5e94cc6..9e06718 100644 --- a/src/noise.ts +++ b/src/noise.ts @@ -6,13 +6,15 @@ import ensureBuffer from 'it-buffer'; import pipe from 'it-pipe'; import lp from 'it-length-prefixed'; -import { Handshake } from "./handshake-xx"; +import { Handshake as XX } from "./handshake-xx"; import { generateKeypair } from "./utils"; import { uint16BEDecode, uint16BEEncode } from "./encoder"; 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 {XXHandshake} from "./handshakes/xx"; +import {HandshakeInterface} from "./@types/handshake-interface"; export type WrappedConnection = ReturnType; @@ -89,24 +91,22 @@ export class Noise implements NoiseConnection { isInitiator: boolean, libp2pPublicKey: bytes, remotePeer: PeerId, - ): Promise { + ): Promise { + // TODO: Implement noise pipes + if (false) { - // TODO: Implement noise pipes } else { - return await this.performXXHandshake(connection, isInitiator, libp2pPublicKey, remotePeer) + const prologue = Buffer.from(this.protocol); + const handshake = new XX(isInitiator, this.privateKey, libp2pPublicKey, prologue, this.staticKeys, connection, remotePeer); + + return await this.performXXHandshake(handshake); } } private async performXXHandshake( - connection: WrappedConnection, - isInitiator: boolean, - libp2pPublicKey: bytes, - remotePeer: PeerId, - ): Promise { - const prologue = Buffer.from(this.protocol); - const handshake = new Handshake(isInitiator, this.privateKey, libp2pPublicKey, prologue, this.staticKeys, connection, remotePeer); - + handshake: XX + ): Promise { try { await handshake.propose(); await handshake.exchange(); @@ -120,7 +120,7 @@ export class Noise implements NoiseConnection { private async createSecureConnection( connection: WrappedConnection, - handshake: Handshake, + handshake: HandshakeInterface, ): Promise { // Create encryption box/unbox wrapper const [secure, user] = DuplexPair();