mirror of https://github.com/waku-org/js-noise.git
feat: enable meta field to be set
Ref: https://github.com/waku-org/js-waku/issues/1208
This commit is contained in:
parent
174bc32617
commit
4f18b886c9
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "@waku/noise",
|
||||
"version": "0.0.2",
|
||||
"version": "0.0.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@waku/noise",
|
||||
"version": "0.0.2",
|
||||
"version": "0.0.3",
|
||||
"license": "Apache-2.0 OR MIT",
|
||||
"dependencies": {
|
||||
"@stablelib/chacha20poly1305": "^1.0.1",
|
||||
|
|
24
src/codec.ts
24
src/codec.ts
|
@ -1,5 +1,5 @@
|
|||
import { DecodedMessage } from "@waku/core/lib/message/version_0";
|
||||
import type { IDecodedMessage, IDecoder, IEncoder, IMessage, IProtoMessage } from "@waku/interfaces";
|
||||
import type { IDecodedMessage, IDecoder, IEncoder, IMessage, IMetaSetter, IProtoMessage } from "@waku/interfaces";
|
||||
import { WakuMessage } from "@waku/proto";
|
||||
import debug from "debug";
|
||||
|
||||
|
@ -120,10 +120,17 @@ export class NoiseSecureMessage extends DecodedMessage implements IDecodedMessag
|
|||
*/
|
||||
export class NoiseSecureTransferEncoder implements IEncoder {
|
||||
/**
|
||||
* @param contentTopic content topic on which the encoded WakuMessages were sent
|
||||
* @param hsResult handshake result obtained after the handshake is successful
|
||||
* @param contentTopic content topic on which the encoded WakuMessages were sent.
|
||||
* @param hsResult handshake result obtained after the handshake is successful.
|
||||
* @param ephemeral whether messages should be tagged as ephemeral defaults to true.
|
||||
* @param metaSetter callback function that set the `meta` field.
|
||||
*/
|
||||
constructor(public contentTopic: string, private hsResult: HandshakeResult, public ephemeral: boolean = true) {}
|
||||
constructor(
|
||||
public contentTopic: string,
|
||||
private hsResult: HandshakeResult,
|
||||
public ephemeral: boolean = true,
|
||||
public metaSetter?: IMetaSetter
|
||||
) {}
|
||||
|
||||
async toWire(message: IMessage): Promise<Uint8Array | undefined> {
|
||||
const protoMessage = await this.toProtoObj(message);
|
||||
|
@ -142,7 +149,7 @@ export class NoiseSecureTransferEncoder implements IEncoder {
|
|||
|
||||
const payload = preparedPayload.serialize();
|
||||
|
||||
return {
|
||||
const protoMessage = {
|
||||
payload,
|
||||
rateLimitProof: undefined,
|
||||
ephemeral: this.ephemeral,
|
||||
|
@ -151,6 +158,13 @@ export class NoiseSecureTransferEncoder implements IEncoder {
|
|||
contentTopic: this.contentTopic,
|
||||
timestamp: BigInt(timestamp.valueOf()) * OneMillion,
|
||||
};
|
||||
|
||||
if (this.metaSetter) {
|
||||
const meta = this.metaSetter(protoMessage);
|
||||
return { ...protoMessage, meta };
|
||||
}
|
||||
|
||||
return protoMessage;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { HMACDRBG } from "@stablelib/hmac-drbg";
|
||||
import { randomBytes } from "@stablelib/random";
|
||||
import type { IDecoder, IEncoder, IMessage, ISender } from "@waku/interfaces";
|
||||
import type { IDecoder, IEncoder, IMessage, IProtoMessage, ISender } from "@waku/interfaces";
|
||||
import { expect } from "chai";
|
||||
import { EventEmitter } from "eventemitter3";
|
||||
import { pEvent } from "p-event";
|
||||
|
@ -13,6 +13,15 @@ import { ResponderParameters, WakuPairing } from "./pairing";
|
|||
|
||||
const PUBSUB_TOPIC = "default";
|
||||
|
||||
const EMPTY_PROTOMESSAGE = {
|
||||
timestamp: undefined,
|
||||
contentTopic: "",
|
||||
ephemeral: undefined,
|
||||
meta: undefined,
|
||||
rateLimitProof: undefined,
|
||||
version: undefined,
|
||||
};
|
||||
|
||||
describe("js-noise: pairing object", () => {
|
||||
const rng = new HMACDRBG();
|
||||
|
||||
|
@ -117,4 +126,75 @@ describe("js-noise: pairing object", () => {
|
|||
expect(message).to.be.equals("pairing has timed out");
|
||||
}
|
||||
});
|
||||
|
||||
it("pairs and `meta` field is encoded", async function () {
|
||||
const bobStaticKey = generateX25519KeyPair();
|
||||
const aliceStaticKey = generateX25519KeyPair();
|
||||
|
||||
// Encode the length of the payload
|
||||
// Not a relevant real life example
|
||||
const metaSetter = (msg: IProtoMessage & { meta: undefined }): Uint8Array => {
|
||||
const buffer = new ArrayBuffer(4);
|
||||
const view = new DataView(buffer);
|
||||
view.setUint32(0, msg.payload.length, false);
|
||||
return new Uint8Array(buffer);
|
||||
};
|
||||
|
||||
const recvParameters = new ResponderParameters();
|
||||
const bobPairingObj = new WakuPairing(sender, responder, bobStaticKey, recvParameters, undefined, { metaSetter });
|
||||
const bobExecP1 = bobPairingObj.execute();
|
||||
|
||||
// Confirmation is done by manually
|
||||
confirmAuthCodeFlow(bobPairingObj, true);
|
||||
|
||||
const initParameters = bobPairingObj.getPairingInfo();
|
||||
const alicePairingObj = new WakuPairing(sender, responder, aliceStaticKey, initParameters, undefined, {
|
||||
metaSetter,
|
||||
});
|
||||
const aliceExecP1 = alicePairingObj.execute();
|
||||
|
||||
// Confirmation is done manually
|
||||
confirmAuthCodeFlow(alicePairingObj, true);
|
||||
|
||||
const [bobCodecs, aliceCodecs] = await Promise.all([bobExecP1, aliceExecP1]);
|
||||
|
||||
const bobEncoder = bobCodecs[0];
|
||||
const bobDecoder = bobCodecs[1];
|
||||
const aliceEncoder = aliceCodecs[0];
|
||||
const aliceDecoder = aliceCodecs[1];
|
||||
|
||||
// We test read/write of random messages exchanged between Alice and Bob
|
||||
// Note that we exchange more than the number of messages contained in the nametag buffer to test if they are filled correctly as the communication proceeds
|
||||
for (let i = 0; i < 10 * MessageNametagBufferSize; i++) {
|
||||
// Alice writes to Bob
|
||||
let message = randomBytes(32, rng);
|
||||
let encodedMsg = await aliceEncoder.toWire({ payload: message });
|
||||
let readMessageProto = await bobDecoder.fromWireToProtoObj(encodedMsg!);
|
||||
let readMessage = await bobDecoder.fromProtoObj(PUBSUB_TOPIC, readMessageProto!);
|
||||
|
||||
expect(uint8ArrayEquals(message, readMessage!.payload)).to.be.true;
|
||||
|
||||
let expectedMeta = metaSetter({
|
||||
...EMPTY_PROTOMESSAGE,
|
||||
payload: readMessageProto!.payload,
|
||||
});
|
||||
|
||||
expect(readMessage!.meta).to.deep.eq(expectedMeta);
|
||||
|
||||
// Bob writes to Alice
|
||||
message = randomBytes(32, rng);
|
||||
encodedMsg = await bobEncoder.toWire({ payload: message });
|
||||
readMessageProto = await aliceDecoder.fromWireToProtoObj(encodedMsg!);
|
||||
readMessage = await aliceDecoder.fromProtoObj(PUBSUB_TOPIC, readMessageProto!);
|
||||
|
||||
expect(uint8ArrayEquals(message, readMessage!.payload)).to.be.true;
|
||||
|
||||
expectedMeta = metaSetter({
|
||||
...EMPTY_PROTOMESSAGE,
|
||||
payload: readMessageProto!.payload,
|
||||
});
|
||||
|
||||
expect(readMessage!.meta).to.deep.eq(expectedMeta);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { HMACDRBG } from "@stablelib/hmac-drbg";
|
||||
import { randomBytes } from "@stablelib/random";
|
||||
import type { IDecoder, ISender } from "@waku/interfaces";
|
||||
import type { IDecoder, IMetaSetter, ISender } from "@waku/interfaces";
|
||||
import debug from "debug";
|
||||
import { EventEmitter } from "eventemitter3";
|
||||
import { pEvent } from "p-event";
|
||||
|
@ -55,6 +55,11 @@ function delay(ms: number): Promise<void> {
|
|||
|
||||
const rng = new HMACDRBG();
|
||||
|
||||
export interface EncoderParameters {
|
||||
ephemeral?: boolean;
|
||||
metaSetter?: IMetaSetter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiator parameters used to setup the pairing object
|
||||
*/
|
||||
|
@ -108,13 +113,15 @@ export class WakuPairing {
|
|||
* @param myStaticKey x25519 keypair
|
||||
* @param pairingParameters Pairing parameters (depending if this is the initiator or responder)
|
||||
* @param myEphemeralKey optional ephemeral key
|
||||
* @param encoderParameters optional parameters for the resulting encoders
|
||||
*/
|
||||
constructor(
|
||||
private sender: ISender,
|
||||
private responder: Responder,
|
||||
private myStaticKey: KeyPair,
|
||||
pairingParameters: InitiatorParameters | ResponderParameters,
|
||||
private myEphemeralKey: KeyPair = generateX25519KeyPair()
|
||||
private myEphemeralKey: KeyPair = generateX25519KeyPair(),
|
||||
private readonly encoderParameters: EncoderParameters = {}
|
||||
) {
|
||||
this.randomFixLenVal = randomBytes(32, rng);
|
||||
this.myCommittedStaticKey = commitPublicKey(this.myStaticKey.publicKey, this.randomFixLenVal);
|
||||
|
@ -293,7 +300,7 @@ export class WakuPairing {
|
|||
|
||||
this.eventEmitter.emit("pairingComplete");
|
||||
|
||||
return WakuPairing.getSecureCodec(this.contentTopic, this.handshakeResult);
|
||||
return WakuPairing.getSecureCodec(this.contentTopic, this.handshakeResult, this.encoderParameters);
|
||||
}
|
||||
|
||||
private async responderHandshake(): Promise<[NoiseSecureTransferEncoder, NoiseSecureTransferDecoder]> {
|
||||
|
@ -350,7 +357,7 @@ export class WakuPairing {
|
|||
|
||||
this.eventEmitter.emit("pairingComplete");
|
||||
|
||||
return WakuPairing.getSecureCodec(this.contentTopic, this.handshakeResult);
|
||||
return WakuPairing.getSecureCodec(this.contentTopic, this.handshakeResult, this.encoderParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -358,13 +365,20 @@ export class WakuPairing {
|
|||
* to continue a session using a stored hsResult
|
||||
* @param contentTopic Content topic for the waku messages
|
||||
* @param hsResult Noise Pairing result
|
||||
* @param encoderParameters Parameters for the resulting encoder
|
||||
* @returns an array with [NoiseSecureTransferEncoder, NoiseSecureTransferDecoder]
|
||||
*/
|
||||
static getSecureCodec(
|
||||
contentTopic: string,
|
||||
hsResult: HandshakeResult
|
||||
hsResult: HandshakeResult,
|
||||
encoderParameters: EncoderParameters
|
||||
): [NoiseSecureTransferEncoder, NoiseSecureTransferDecoder] {
|
||||
const secureEncoder = new NoiseSecureTransferEncoder(contentTopic, hsResult);
|
||||
const secureEncoder = new NoiseSecureTransferEncoder(
|
||||
contentTopic,
|
||||
hsResult,
|
||||
encoderParameters.ephemeral,
|
||||
encoderParameters.metaSetter
|
||||
);
|
||||
const secureDecoder = new NoiseSecureTransferDecoder(contentTopic, hsResult);
|
||||
|
||||
return [secureEncoder, secureDecoder];
|
||||
|
|
Loading…
Reference in New Issue