mirror of
https://github.com/fluencelabs/js-libp2p-noise
synced 2025-04-26 11:42:23 +00:00
Write and test IK stages
This commit is contained in:
parent
6ee5c70af9
commit
eeaaa8cc84
@ -5,6 +5,8 @@ import {bytes, bytes32} from "./@types/basic";
|
|||||||
import {KeyPair, PeerId} from "./@types/libp2p";
|
import {KeyPair, PeerId} from "./@types/libp2p";
|
||||||
import {IHandshake} from "./@types/handshake-interface";
|
import {IHandshake} from "./@types/handshake-interface";
|
||||||
import {Buffer} from "buffer";
|
import {Buffer} from "buffer";
|
||||||
|
import {decode0, decode1, encode0, encode1} from "./encoder";
|
||||||
|
import {verifySignedPayload} from "./utils";
|
||||||
|
|
||||||
export class IKHandshake implements IHandshake {
|
export class IKHandshake implements IHandshake {
|
||||||
public isInitiator: boolean;
|
public isInitiator: boolean;
|
||||||
@ -38,6 +40,38 @@ export class IKHandshake implements IHandshake {
|
|||||||
this.session = this.ik.initSession(this.isInitiator, this.prologue, this.staticKeypair, remoteStaticKey);
|
this.session = this.ik.initSession(this.isInitiator, this.prologue, this.staticKeypair, remoteStaticKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async stage0(): Promise<void> {
|
||||||
|
if (this.isInitiator) {
|
||||||
|
const messageBuffer = this.ik.sendMessage(this.session, this.payload);
|
||||||
|
this.connection.writeLP(encode0(messageBuffer));
|
||||||
|
} else {
|
||||||
|
const receivedMessageBuffer = decode0(await this.connection.readLP());
|
||||||
|
const plaintext = this.ik.recvMessage(this.session, receivedMessageBuffer);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await verifySignedPayload(receivedMessageBuffer.ns, plaintext, this.remotePeer.id);
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(`Error occurred while verifying signed payload: ${e.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async stage1(): Promise<void> {
|
||||||
|
if (this.isInitiator) {
|
||||||
|
const receivedMessageBuffer = decode1(await this.connection.readLP());
|
||||||
|
const plaintext = this.ik.recvMessage(this.session, receivedMessageBuffer);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await verifySignedPayload(receivedMessageBuffer.ns, plaintext, this.remotePeer.id);
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(`Error occurred while verifying signed payload: ${e.message}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const messageBuffer = this.ik.sendMessage(this.session, this.payload);
|
||||||
|
this.connection.writeLP(encode1(messageBuffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public decrypt(ciphertext: Buffer, session: NoiseSession): Buffer {
|
public decrypt(ciphertext: Buffer, session: NoiseSession): Buffer {
|
||||||
const cs = this.getCS(session, false);
|
const cs = this.getCS(session, false);
|
||||||
return this.ik.decryptWithAd(cs, Buffer.alloc(0), ciphertext);
|
return this.ik.decryptWithAd(cs, Buffer.alloc(0), ciphertext);
|
||||||
|
@ -179,7 +179,9 @@ export class Noise implements INoiseConnection {
|
|||||||
handshake: IKHandshake,
|
handshake: IKHandshake,
|
||||||
payload: bytes,
|
payload: bytes,
|
||||||
): Promise<IKHandshake> {
|
): Promise<IKHandshake> {
|
||||||
// TODO
|
|
||||||
|
await handshake.stage0();
|
||||||
|
await handshake.stage1();
|
||||||
|
|
||||||
return handshake;
|
return handshake;
|
||||||
}
|
}
|
||||||
|
56
test/ik-handshake.test.ts
Normal file
56
test/ik-handshake.test.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import Wrap from "it-pb-rpc";
|
||||||
|
import Duplex from 'it-pair/duplex';
|
||||||
|
import {Buffer} from "buffer";
|
||||||
|
|
||||||
|
import {createPeerIdsFromFixtures} from "./fixtures/peer";
|
||||||
|
import {generateKeypair, getPayload} from "../src/utils";
|
||||||
|
import {IKHandshake} from "../src/handshake-ik";
|
||||||
|
import {assert} from "chai";
|
||||||
|
|
||||||
|
describe("IK Handshake", () => {
|
||||||
|
let peerA, peerB, fakePeer;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
[peerA, peerB, fakePeer] = await createPeerIdsFromFixtures(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should finish both stages as initiator and responder", async() => {
|
||||||
|
try {
|
||||||
|
const duplex = Duplex();
|
||||||
|
const connectionFrom = Wrap(duplex[0]);
|
||||||
|
const connectionTo = Wrap(duplex[1]);
|
||||||
|
|
||||||
|
const prologue = Buffer.from('/noise');
|
||||||
|
const staticKeysInitiator = generateKeypair();
|
||||||
|
const staticKeysResponder = generateKeypair();
|
||||||
|
|
||||||
|
const initPayload = await getPayload(peerA, staticKeysInitiator.publicKey);
|
||||||
|
const handshakeInit = new IKHandshake(true, initPayload, prologue, staticKeysInitiator, connectionFrom, peerB, staticKeysResponder.publicKey);
|
||||||
|
|
||||||
|
const respPayload = await getPayload(peerB, staticKeysResponder.publicKey);
|
||||||
|
const handshakeResp = new IKHandshake(false, respPayload, prologue, staticKeysResponder, connectionTo, peerA, staticKeysInitiator.publicKey);
|
||||||
|
|
||||||
|
await handshakeInit.stage0();
|
||||||
|
await handshakeResp.stage0();
|
||||||
|
|
||||||
|
await handshakeResp.stage1();
|
||||||
|
await handshakeInit.stage1();
|
||||||
|
|
||||||
|
// Test shared key
|
||||||
|
if (handshakeInit.session.cs1 && handshakeResp.session.cs1 && handshakeInit.session.cs2 && handshakeResp.session.cs2) {
|
||||||
|
assert(handshakeInit.session.cs1.k.equals(handshakeResp.session.cs1.k));
|
||||||
|
assert(handshakeInit.session.cs2.k.equals(handshakeResp.session.cs2.k));
|
||||||
|
} else {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test encryption and decryption
|
||||||
|
const encrypted = handshakeInit.encrypt(Buffer.from("encryptthis"), handshakeInit.session);
|
||||||
|
const decrypted = handshakeResp.decrypt(encrypted, handshakeResp.session);
|
||||||
|
assert(decrypted.equals(Buffer.from("encryptthis")));
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
assert(false, e.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user