mirror of
https://github.com/fluencelabs/js-libp2p-noise
synced 2025-04-25 14:12:30 +00:00
Create IK and read ephemeral keys
This commit is contained in:
parent
e797dc2741
commit
a514ededa1
@ -1,10 +1,12 @@
|
||||
import {WrappedConnection} from "./noise";
|
||||
import {IKHandshake} from "./handshakes/ik";
|
||||
import {NoiseSession} from "./@types/handshake";
|
||||
import {bytes, bytes32} from "./@types/basic";
|
||||
import {KeyPair, PeerId} from "./@types/libp2p";
|
||||
import {WrappedConnection} from "./noise";
|
||||
import {IKHandshake} from "./handshakes/ik";
|
||||
import {HandshakeInterface} from "./@types/handshake-interface";
|
||||
import {Buffer} from "buffer";
|
||||
|
||||
export class Handshake { // implements HandshakeHandler
|
||||
export class Handshake implements HandshakeInterface {
|
||||
public isInitiator: boolean;
|
||||
public session: NoiseSession;
|
||||
|
||||
@ -41,4 +43,30 @@ export class Handshake { // implements HandshakeHandler
|
||||
const remoteStaticKeys = this.staticKeys;
|
||||
this.session = this.ik.initSession(this.isInitiator, this.prologue, this.staticKeys, remoteStaticKeys.publicKey);
|
||||
}
|
||||
|
||||
public decrypt(ciphertext: Buffer, session: NoiseSession): Buffer {
|
||||
const cs = this.getCS(session, false);
|
||||
return this.ik.decryptWithAd(cs, Buffer.alloc(0), ciphertext);
|
||||
}
|
||||
|
||||
public encrypt(plaintext: Buffer, session: NoiseSession): Buffer {
|
||||
const cs = this.getCS(session);
|
||||
return this.ik.encryptWithAd(cs, Buffer.alloc(0), plaintext);
|
||||
}
|
||||
|
||||
public getRemoteEphemeralKeys(): KeyPair | undefined {
|
||||
return this.session.hs.e;
|
||||
}
|
||||
|
||||
private getCS(session: NoiseSession, encryption = true) {
|
||||
if (!session.cs1 || !session.cs2) {
|
||||
throw new Error("Handshake not completed properly, cipher state does not exist.");
|
||||
}
|
||||
|
||||
if (this.isInitiator) {
|
||||
return encryption ? session.cs1 : session.cs2;
|
||||
} else {
|
||||
return encryption ? session.cs2 : session.cs1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ export class Handshake implements HandshakeInterface {
|
||||
staticKeys: KeyPair,
|
||||
connection: WrappedConnection,
|
||||
remotePeer: PeerId,
|
||||
ephemeralKeys?: KeyPair,
|
||||
handshake?: XXHandshake,
|
||||
) {
|
||||
this.isInitiator = isInitiator;
|
||||
|
@ -27,9 +27,14 @@ export class XXHandshake extends AbstractHandshake {
|
||||
return { ss, s, rs, psk, re };
|
||||
}
|
||||
|
||||
private writeMessageA(hs: HandshakeState, payload: bytes): MessageBuffer {
|
||||
private writeMessageA(hs: HandshakeState, payload: bytes, e?: KeyPair): MessageBuffer {
|
||||
const ns = Buffer.alloc(0);
|
||||
hs.e = generateKeypair();
|
||||
|
||||
if (e) {
|
||||
hs.e = e;
|
||||
} else {
|
||||
hs.e = generateKeypair();
|
||||
}
|
||||
|
||||
const ne = hs.e.publicKey;
|
||||
|
||||
@ -128,10 +133,10 @@ export class XXHandshake extends AbstractHandshake {
|
||||
};
|
||||
}
|
||||
|
||||
public sendMessage(session: NoiseSession, message: bytes): MessageBuffer {
|
||||
public sendMessage(session: NoiseSession, message: bytes, ephemeral?: KeyPair): MessageBuffer {
|
||||
let messageBuffer: MessageBuffer;
|
||||
if (session.mc.eqn(0)) {
|
||||
messageBuffer = this.writeMessageA(session.hs, message);
|
||||
messageBuffer = this.writeMessageA(session.hs, message, ephemeral);
|
||||
} else if (session.mc.eqn(1)) {
|
||||
messageBuffer = this.writeMessageB(session.hs, message);
|
||||
} else if (session.mc.eqn(2)) {
|
||||
|
22
src/noise.ts
22
src/noise.ts
@ -7,6 +7,7 @@ import pipe from 'it-pipe';
|
||||
import lp from 'it-length-prefixed';
|
||||
|
||||
import { Handshake as XX } from "./handshake-xx";
|
||||
import { Handshake as IK } from "./handshake-ik";
|
||||
import { generateKeypair } from "./utils";
|
||||
import { uint16BEDecode, uint16BEEncode } from "./encoder";
|
||||
import { decryptStream, encryptStream } from "./crypto";
|
||||
@ -21,6 +22,7 @@ export type WrappedConnection = ReturnType<typeof Wrap>;
|
||||
export class Noise implements NoiseConnection {
|
||||
public protocol = "/noise";
|
||||
|
||||
private readonly prologue = Buffer.from(this.protocol);
|
||||
private readonly privateKey: bytes;
|
||||
private readonly staticKeys: KeyPair;
|
||||
private readonly earlyData?: bytes;
|
||||
@ -92,21 +94,29 @@ export class Noise implements NoiseConnection {
|
||||
libp2pPublicKey: bytes,
|
||||
remotePeer: PeerId,
|
||||
): Promise<HandshakeInterface> {
|
||||
|
||||
// TODO: Implement noise pipes
|
||||
|
||||
if (false) {
|
||||
const IKhandshake = new IK(isInitiator, this.privateKey, libp2pPublicKey, this.prologue, this.staticKeys, connection, remotePeer);
|
||||
|
||||
if(true) {
|
||||
// XX fallback
|
||||
const ephemeralKeys = IKhandshake.getRemoteEphemeralKeys();
|
||||
return await this.performXXHandshake(connection, isInitiator, libp2pPublicKey, remotePeer, ephemeralKeys);
|
||||
} else {
|
||||
const prologue = Buffer.from(this.protocol);
|
||||
const handshake = new XX(isInitiator, this.privateKey, libp2pPublicKey, prologue, this.staticKeys, connection, remotePeer);
|
||||
|
||||
return await this.performXXHandshake(handshake);
|
||||
return await this.performXXHandshake(connection, isInitiator, libp2pPublicKey, remotePeer);
|
||||
}
|
||||
}
|
||||
|
||||
private async performXXHandshake(
|
||||
handshake: XX
|
||||
connection: WrappedConnection,
|
||||
isInitiator: boolean,
|
||||
libp2pPublicKey: bytes,
|
||||
remotePeer: PeerId,
|
||||
ephemeralKeys?: KeyPair,
|
||||
): Promise<HandshakeInterface> {
|
||||
const handshake = new XX(isInitiator, this.privateKey, libp2pPublicKey, this.prologue, this.staticKeys, connection, remotePeer, ephemeralKeys);
|
||||
|
||||
try {
|
||||
await handshake.propose();
|
||||
await handshake.exchange();
|
||||
|
@ -61,7 +61,7 @@ describe("Noise", () => {
|
||||
const xx = new XXHandshake();
|
||||
const { privateKey: libp2pPrivKey, publicKey: libp2pPubKey } = getKeyPairFromPeerId(remotePeer);
|
||||
|
||||
const handshake = new Handshake(false, libp2pPrivKey, libp2pPubKey, prologue, staticKeys, wrapped, localPeer, xx);
|
||||
const handshake = new Handshake(false, libp2pPrivKey, libp2pPubKey, prologue, staticKeys, wrapped, localPeer, undefined, xx);
|
||||
|
||||
let receivedMessageBuffer = decodeMessageBuffer((await wrapped.readLP()).slice());
|
||||
// The first handshake message contains the initiator's ephemeral public key
|
||||
|
Loading…
x
Reference in New Issue
Block a user