From d9b8fdc98e60778b418783a0cf3dcaf9289a4584 Mon Sep 17 00:00:00 2001 From: Richard Ramos Date: Mon, 20 Nov 2023 15:14:02 -0400 Subject: [PATCH] refactor: tagLen as parameter --- src/crypto.ts | 4 +--- src/index.spec.ts | 20 +++++++++++--------- src/pairing.ts | 2 +- src/patterns.ts | 19 +++++++++++++------ src/payload.ts | 33 ++++++++++++++------------------- src/waku-noise-pairing.spec.ts | 2 +- 6 files changed, 41 insertions(+), 39 deletions(-) diff --git a/src/crypto.ts b/src/crypto.ts index 215b07f..1bdb323 100644 --- a/src/crypto.ts +++ b/src/crypto.ts @@ -1,4 +1,4 @@ -import { ChaCha20Poly1305, TAG_LENGTH } from "@stablelib/chacha20poly1305"; +import { ChaCha20Poly1305 } from "@stablelib/chacha20poly1305"; import { Hash } from "@stablelib/hash"; import { HKDF as hkdf } from "@stablelib/hkdf"; import { hash } from "@stablelib/sha256"; @@ -10,8 +10,6 @@ import type { KeyPair } from "./@types/keypair.js"; export const Curve25519KeySize = x25519.PUBLIC_KEY_LENGTH; -export const ChachaPolyTagLen = TAG_LENGTH; - /** * Generate hash using SHA2-256 * @param data data to hash diff --git a/src/index.spec.ts b/src/index.spec.ts index 9d1901f..c8fb8fd 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -8,7 +8,7 @@ import { Handshake, HandshakeStepResult } from "./handshake"; import { MessageNametagBuffer, MessageNametagLength } from "./messagenametag"; import { CipherState, createEmptyKey, SymmetricState } from "./noise"; import { MAX_NONCE, Nonce } from "./nonce"; -import { NoiseHandshakePatterns } from "./patterns"; +import { NoiseHandshakePatterns, PayloadV2ProtocolIDs } from "./patterns"; import { PayloadV2 } from "./payload"; import { ChaChaPolyCipherState, NoisePublicKey } from "./publickey"; @@ -38,13 +38,15 @@ function randomNoisePublicKey(): NoisePublicKey { function randomPayloadV2(rng: HMACDRBG): PayloadV2 { const messageNametag = randomBytes(MessageNametagLength, rng); const protocolId = 14; + const protocolName = Object.keys(PayloadV2ProtocolIDs).find((key) => PayloadV2ProtocolIDs[key] === protocolId); + const handshakePattern = NoiseHandshakePatterns[protocolName!]; const handshakeMessage = [randomNoisePublicKey(), randomNoisePublicKey(), randomNoisePublicKey()]; const transportMessage = randomBytes(128); - return new PayloadV2(messageNametag, protocolId, handshakeMessage, transportMessage); + return new PayloadV2(messageNametag, protocolId, handshakePattern.tagLen, handshakeMessage, transportMessage); } describe("js-noise", () => { - const rng = new HMACDRBG(); + const rng = new HMACDRBG(undefined); it("ChaChaPoly Encryption/Decryption: random byte sequences", function () { const cipherState = randomChaChaPolyCipherState(rng); @@ -241,7 +243,7 @@ describe("js-noise", () => { it("Noise State Machine: Cipher State primitives", function () { // We select one supported handshake pattern and we initialize a symmetric state - const hsPattern = NoiseHandshakePatterns.XX; + const hsPattern = NoiseHandshakePatterns.Noise_XX_25519_ChaChaPoly_SHA256; let symmetricState = new SymmetricState(hsPattern); // We get all the Symmetric State field @@ -352,8 +354,8 @@ describe("js-noise", () => { expect(uint8ArrayEquals(cs1.getKey(), cs2.getKey())).to.be.false; }); - it("Noise XX Handhshake and message encryption (extended test)", function () { - const hsPattern = NoiseHandshakePatterns.XX; + it("Noise XX Handshake and message encryption (extended test)", function () { + const hsPattern = NoiseHandshakePatterns.Noise_XX_25519_ChaChaPoly_SHA256; // We initialize Alice's and Bob's Handshake State const aliceStaticKey = generateX25519KeyPair(); @@ -464,7 +466,7 @@ describe("js-noise", () => { }); it("Noise XXpsk0 Handhshake and message encryption (short test)", function () { - const hsPattern = NoiseHandshakePatterns.XXpsk0; + const hsPattern = NoiseHandshakePatterns.Noise_XXpsk0_25519_ChaChaPoly_SHA256; // We generate a random psk const psk = randomBytes(32, rng); @@ -559,7 +561,7 @@ describe("js-noise", () => { }); it("Noise K1K1 Handhshake and message encryption (short test)", function () { - const hsPattern = NoiseHandshakePatterns.K1K1; + const hsPattern = NoiseHandshakePatterns.Noise_K1K1_25519_ChaChaPoly_SHA256; // We initialize Alice's and Bob's Handshake State const aliceStaticKey = generateX25519KeyPair(); @@ -661,7 +663,7 @@ describe("js-noise", () => { }); it("Noise XK1 Handhshake and message encryption (short test)", function () { - const hsPattern = NoiseHandshakePatterns.XK1; + const hsPattern = NoiseHandshakePatterns.Noise_XK1_25519_ChaChaPoly_SHA256; // We initialize Alice's and Bob's Handshake State const aliceStaticKey = generateX25519KeyPair(); diff --git a/src/pairing.ts b/src/pairing.ts index 5c23135..1579354 100644 --- a/src/pairing.ts +++ b/src/pairing.ts @@ -124,7 +124,7 @@ export class WakuPairing { const preMessagePKs = [NoisePublicKey.fromPublicKey(this.qr.ephemeralKey)]; this.handshake = new Handshake({ - hsPattern: NoiseHandshakePatterns.WakuPairing, + hsPattern: NoiseHandshakePatterns.Noise_WakuPairing_25519_ChaChaPoly_SHA256, ephemeralKey: myEphemeralKey, staticKey: myStaticKey, prologue: this.qr.toByteArray(), diff --git a/src/patterns.ts b/src/patterns.ts index 5e11a47..4ce1db4 100644 --- a/src/patterns.ts +++ b/src/patterns.ts @@ -1,3 +1,4 @@ +import { TAG_LENGTH as ChaChaPolyTagLen } from "@stablelib/chacha20poly1305"; import { Hash } from "@stablelib/hash"; import { SHA256 } from "@stablelib/sha256"; @@ -74,6 +75,7 @@ export class HandshakePattern { constructor( public readonly name: string, public readonly hash: new () => Hash, + public readonly tagLen: number, public readonly preMessagePatterns: Array, public readonly messagePatterns: Array ) {} @@ -101,10 +103,11 @@ export class HandshakePattern { /** * Supported Noise handshake patterns as defined in https://rfc.vac.dev/spec/35/#specification */ -export const NoiseHandshakePatterns = { - K1K1: new HandshakePattern( +export const NoiseHandshakePatterns: Record = { + Noise_K1K1_25519_ChaChaPoly_SHA256: new HandshakePattern( "Noise_K1K1_25519_ChaChaPoly_SHA256", SHA256, + ChaChaPolyTagLen, [ new PreMessagePattern(MessageDirection.r, [NoiseTokens.s]), new PreMessagePattern(MessageDirection.l, [NoiseTokens.s]), @@ -115,9 +118,10 @@ export const NoiseHandshakePatterns = { new MessagePattern(MessageDirection.r, [NoiseTokens.se]), ] ), - XK1: new HandshakePattern( + Noise_XK1_25519_ChaChaPoly_SHA256: new HandshakePattern( "Noise_XK1_25519_ChaChaPoly_SHA256", SHA256, + ChaChaPolyTagLen, [new PreMessagePattern(MessageDirection.l, [NoiseTokens.s])], [ new MessagePattern(MessageDirection.r, [NoiseTokens.e]), @@ -125,9 +129,10 @@ export const NoiseHandshakePatterns = { new MessagePattern(MessageDirection.r, [NoiseTokens.s, NoiseTokens.se]), ] ), - XX: new HandshakePattern( + Noise_XX_25519_ChaChaPoly_SHA256: new HandshakePattern( "Noise_XX_25519_ChaChaPoly_SHA256", SHA256, + ChaChaPolyTagLen, [], [ new MessagePattern(MessageDirection.r, [NoiseTokens.e]), @@ -135,9 +140,10 @@ export const NoiseHandshakePatterns = { new MessagePattern(MessageDirection.r, [NoiseTokens.s, NoiseTokens.se]), ] ), - XXpsk0: new HandshakePattern( + Noise_XXpsk0_25519_ChaChaPoly_SHA256: new HandshakePattern( "Noise_XXpsk0_25519_ChaChaPoly_SHA256", SHA256, + ChaChaPolyTagLen, [], [ new MessagePattern(MessageDirection.r, [NoiseTokens.psk, NoiseTokens.e]), @@ -145,9 +151,10 @@ export const NoiseHandshakePatterns = { new MessagePattern(MessageDirection.r, [NoiseTokens.s, NoiseTokens.se]), ] ), - WakuPairing: new HandshakePattern( + Noise_WakuPairing_25519_ChaChaPoly_SHA256: new HandshakePattern( "Noise_WakuPairing_25519_ChaChaPoly_SHA256", SHA256, + ChaChaPolyTagLen, [new PreMessagePattern(MessageDirection.l, [NoiseTokens.e])], [ new MessagePattern(MessageDirection.r, [NoiseTokens.e, NoiseTokens.ee]), diff --git a/src/payload.ts b/src/payload.ts index f1bb441..43bd0c1 100644 --- a/src/payload.ts +++ b/src/payload.ts @@ -2,9 +2,9 @@ import { concat as uint8ArrayConcat } from "uint8arrays/concat"; import { equals as uint8ArrayEquals } from "uint8arrays/equals"; import { MessageNametag } from "./@types/handshake.js"; -import { ChachaPolyTagLen, Curve25519KeySize } from "./crypto.js"; +import { Curve25519KeySize } from "./crypto.js"; import { MessageNametagLength } from "./messagenametag.js"; -import { PayloadV2ProtocolIDs } from "./patterns.js"; +import { NoiseHandshakePatterns, PayloadV2ProtocolIDs } from "./patterns.js"; import { NoisePublicKey } from "./publickey.js"; import { readUIntLE, writeUIntLE } from "./utils.js"; @@ -15,22 +15,13 @@ import { readUIntLE, writeUIntLE } from "./utils.js"; * and the transport message */ export class PayloadV2 { - messageNametag: MessageNametag; - protocolId: number; - handshakeMessage: Array; - transportMessage: Uint8Array; - constructor( - messageNametag: MessageNametag = new Uint8Array(MessageNametagLength), - protocolId = 0, - handshakeMessage: Array = [], - transportMessage: Uint8Array = new Uint8Array() - ) { - this.messageNametag = messageNametag; - this.protocolId = protocolId; - this.handshakeMessage = handshakeMessage; - this.transportMessage = transportMessage; - } + public messageNametag: MessageNametag = new Uint8Array(MessageNametagLength), + public protocolId = 0, + public tagLen = 0, + public handshakeMessage: Array = [], + public transportMessage: Uint8Array = new Uint8Array() + ) {} /** * Create a copy of the PayloadV2 @@ -41,6 +32,7 @@ export class PayloadV2 { r.protocolId = this.protocolId; r.transportMessage = new Uint8Array(this.transportMessage); r.messageNametag = new Uint8Array(this.messageNametag); + r.tagLen = this.tagLen; for (let i = 0; i < this.handshakeMessage.length; i++) { r.handshakeMessage.push(this.handshakeMessage[i].clone()); } @@ -146,6 +138,9 @@ export class PayloadV2 { throw new Error("protocolId not found"); } + const pattern = NoiseHandshakePatterns[protocolName]; + const tagLen = pattern ? pattern.tagLen : 0; + i++; // We read the Handshake Message length (1 byte) @@ -174,7 +169,7 @@ export class PayloadV2 { written += pkLen; // If the key is encrypted, we only read the encrypted X coordinate and the authorization tag, and we deserialize into a Noise Public Key } else if (flag === 1) { - const pkLen = 1 + Curve25519KeySize + ChachaPolyTagLen; + const pkLen = 1 + Curve25519KeySize + tagLen; handshakeMessage.push(NoisePublicKey.deserialize(payload.subarray(i, i + pkLen))); i += pkLen; written += pkLen; @@ -191,6 +186,6 @@ export class PayloadV2 { const transportMessage = payload.subarray(i, i + transportMessageLen); i += transportMessageLen; - return new PayloadV2(messageNametag, protocolId, handshakeMessage, transportMessage); + return new PayloadV2(messageNametag, protocolId, tagLen, handshakeMessage, transportMessage); } } diff --git a/src/waku-noise-pairing.spec.ts b/src/waku-noise-pairing.spec.ts index 4e6235f..c475fab 100644 --- a/src/waku-noise-pairing.spec.ts +++ b/src/waku-noise-pairing.spec.ts @@ -27,7 +27,7 @@ describe("Waku Noise Sessions", () => { // Pairing Phase // ========== - const hsPattern = NoiseHandshakePatterns.WakuPairing; + const hsPattern = NoiseHandshakePatterns.Noise_WakuPairing_25519_ChaChaPoly_SHA256; // Alice static/ephemeral key initialization and commitment const aliceStaticKey = generateX25519KeyPair();