Create handshake interface to support performing different handshakes

This commit is contained in:
Belma Gutlic
2020-01-03 15:43:56 +01:00
parent ac12fbf987
commit e797dc2741
5 changed files with 30 additions and 21 deletions

View File

@ -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;
}

View File

@ -1,5 +1,5 @@
import { Buffer } from "buffer";
import { Handshake } from "./handshake-xx";
import {HandshakeInterface} from "./@types/handshake-interface";
interface ReturnEncryptionWrapper {
(source: Iterable<Uint8Array>): AsyncIterableIterator<Uint8Array>;
@ -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);

View File

@ -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;

View File

@ -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<void> {
public async propose(): Promise<void> {
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<void> {
public async exchange(): Promise<void> {
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<void> {
public async finish(earlyData?: bytes): Promise<void> {
if (this.isInitiator) {
logger('Stage 2 - Initiator sending third handshake message.');
const signedPayload = signPayload(this.libp2pPrivateKey, getHandshakePayload(this.staticKeys.publicKey));

View File

@ -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<typeof Wrap>;
@ -89,24 +91,22 @@ export class Noise implements NoiseConnection {
isInitiator: boolean,
libp2pPublicKey: bytes,
remotePeer: PeerId,
): Promise<Handshake> {
): Promise<HandshakeInterface> {
// 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<Handshake> {
const prologue = Buffer.from(this.protocol);
const handshake = new Handshake(isInitiator, this.privateKey, libp2pPublicKey, prologue, this.staticKeys, connection, remotePeer);
handshake: XX
): Promise<HandshakeInterface> {
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<Duplex> {
// Create encryption box/unbox wrapper
const [secure, user] = DuplexPair();