mirror of
https://github.com/fluencelabs/js-libp2p-noise
synced 2025-04-25 14:02:19 +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 {NoiseSession} from "./@types/handshake";
|
||||||
import {bytes, bytes32} from "./@types/basic";
|
import {bytes, bytes32} from "./@types/basic";
|
||||||
import {KeyPair, PeerId} from "./@types/libp2p";
|
import {KeyPair, PeerId} from "./@types/libp2p";
|
||||||
import {WrappedConnection} from "./noise";
|
import {HandshakeInterface} from "./@types/handshake-interface";
|
||||||
import {IKHandshake} from "./handshakes/ik";
|
import {Buffer} from "buffer";
|
||||||
|
|
||||||
export class Handshake { // implements HandshakeHandler
|
export class Handshake implements HandshakeInterface {
|
||||||
public isInitiator: boolean;
|
public isInitiator: boolean;
|
||||||
public session: NoiseSession;
|
public session: NoiseSession;
|
||||||
|
|
||||||
@ -41,4 +43,30 @@ export class Handshake { // implements HandshakeHandler
|
|||||||
const remoteStaticKeys = this.staticKeys;
|
const remoteStaticKeys = this.staticKeys;
|
||||||
this.session = this.ik.initSession(this.isInitiator, this.prologue, this.staticKeys, remoteStaticKeys.publicKey);
|
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,
|
staticKeys: KeyPair,
|
||||||
connection: WrappedConnection,
|
connection: WrappedConnection,
|
||||||
remotePeer: PeerId,
|
remotePeer: PeerId,
|
||||||
|
ephemeralKeys?: KeyPair,
|
||||||
handshake?: XXHandshake,
|
handshake?: XXHandshake,
|
||||||
) {
|
) {
|
||||||
this.isInitiator = isInitiator;
|
this.isInitiator = isInitiator;
|
||||||
|
@ -27,9 +27,14 @@ export class XXHandshake extends AbstractHandshake {
|
|||||||
return { ss, s, rs, psk, re };
|
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);
|
const ns = Buffer.alloc(0);
|
||||||
hs.e = generateKeypair();
|
|
||||||
|
if (e) {
|
||||||
|
hs.e = e;
|
||||||
|
} else {
|
||||||
|
hs.e = generateKeypair();
|
||||||
|
}
|
||||||
|
|
||||||
const ne = hs.e.publicKey;
|
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;
|
let messageBuffer: MessageBuffer;
|
||||||
if (session.mc.eqn(0)) {
|
if (session.mc.eqn(0)) {
|
||||||
messageBuffer = this.writeMessageA(session.hs, message);
|
messageBuffer = this.writeMessageA(session.hs, message, ephemeral);
|
||||||
} else if (session.mc.eqn(1)) {
|
} else if (session.mc.eqn(1)) {
|
||||||
messageBuffer = this.writeMessageB(session.hs, message);
|
messageBuffer = this.writeMessageB(session.hs, message);
|
||||||
} else if (session.mc.eqn(2)) {
|
} 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 lp from 'it-length-prefixed';
|
||||||
|
|
||||||
import { Handshake as XX } from "./handshake-xx";
|
import { Handshake as XX } from "./handshake-xx";
|
||||||
|
import { Handshake as IK } from "./handshake-ik";
|
||||||
import { generateKeypair } from "./utils";
|
import { generateKeypair } from "./utils";
|
||||||
import { uint16BEDecode, uint16BEEncode } from "./encoder";
|
import { uint16BEDecode, uint16BEEncode } from "./encoder";
|
||||||
import { decryptStream, encryptStream } from "./crypto";
|
import { decryptStream, encryptStream } from "./crypto";
|
||||||
@ -21,6 +22,7 @@ export type WrappedConnection = ReturnType<typeof Wrap>;
|
|||||||
export class Noise implements NoiseConnection {
|
export class Noise implements NoiseConnection {
|
||||||
public protocol = "/noise";
|
public protocol = "/noise";
|
||||||
|
|
||||||
|
private readonly prologue = Buffer.from(this.protocol);
|
||||||
private readonly privateKey: bytes;
|
private readonly privateKey: bytes;
|
||||||
private readonly staticKeys: KeyPair;
|
private readonly staticKeys: KeyPair;
|
||||||
private readonly earlyData?: bytes;
|
private readonly earlyData?: bytes;
|
||||||
@ -92,21 +94,29 @@ export class Noise implements NoiseConnection {
|
|||||||
libp2pPublicKey: bytes,
|
libp2pPublicKey: bytes,
|
||||||
remotePeer: PeerId,
|
remotePeer: PeerId,
|
||||||
): Promise<HandshakeInterface> {
|
): Promise<HandshakeInterface> {
|
||||||
|
|
||||||
// TODO: Implement noise pipes
|
// 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 {
|
} else {
|
||||||
const prologue = Buffer.from(this.protocol);
|
return await this.performXXHandshake(connection, isInitiator, libp2pPublicKey, remotePeer);
|
||||||
const handshake = new XX(isInitiator, this.privateKey, libp2pPublicKey, prologue, this.staticKeys, connection, remotePeer);
|
|
||||||
|
|
||||||
return await this.performXXHandshake(handshake);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async performXXHandshake(
|
private async performXXHandshake(
|
||||||
handshake: XX
|
connection: WrappedConnection,
|
||||||
|
isInitiator: boolean,
|
||||||
|
libp2pPublicKey: bytes,
|
||||||
|
remotePeer: PeerId,
|
||||||
|
ephemeralKeys?: KeyPair,
|
||||||
): Promise<HandshakeInterface> {
|
): Promise<HandshakeInterface> {
|
||||||
|
const handshake = new XX(isInitiator, this.privateKey, libp2pPublicKey, this.prologue, this.staticKeys, connection, remotePeer, ephemeralKeys);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await handshake.propose();
|
await handshake.propose();
|
||||||
await handshake.exchange();
|
await handshake.exchange();
|
||||||
|
@ -61,7 +61,7 @@ describe("Noise", () => {
|
|||||||
const xx = new XXHandshake();
|
const xx = new XXHandshake();
|
||||||
const { privateKey: libp2pPrivKey, publicKey: libp2pPubKey } = getKeyPairFromPeerId(remotePeer);
|
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());
|
let receivedMessageBuffer = decodeMessageBuffer((await wrapped.readLP()).slice());
|
||||||
// The first handshake message contains the initiator's ephemeral public key
|
// The first handshake message contains the initiator's ephemeral public key
|
||||||
|
Loading…
x
Reference in New Issue
Block a user