noise-js.test.ts

2.7 KB · raw

1/**2 * Noise NK auth proof cross-check.3 *4 * The JS implementation in `noise-js.ts` MUST produce byte-identical proofs to5 * the native Rust host (see `native/peach-sync-host/src/auth.rs`). The fixed6 * test vector below was captured by running:7 *8 *   cargo test --manifest-path native/peach-sync-host/Cargo.toml \9 *     print_known_proof_for_js_cross_check -- --nocapture10 *11 * If either side ever changes the auth proof format, ONE of the two pinned12 * hex strings (here and in auth.rs) will fail and CI catches the divergence13 * before any device pair gets wedged.14 */1516import { describe, expect, it } from "vitest";17import { generateKeyPair as x25519GenerateKeyPair } from "@stablelib/x25519";1819import { computeAuthProof, bytesToHex } from "./noise-js";2021// Inputs match the Rust test in auth.rs::tests::print_known_proof_for_js_cross_check22const INITIATOR_PRIVATE = new Uint8Array(32).fill(0x01);23const RESPONDER_PRIVATE = new Uint8Array(32).fill(0x02);24const NONCE = new Uint8Array(32).fill(0x03);2526const EXPECTED_INITIATOR_PUBLIC =27  "a4e09292b651c278b9772c569f5fa9bb13d906b46ab68c9df9dc2b4409f8a209";28const EXPECTED_RESPONDER_PUBLIC =29  "ce8d3ad1ccb633ec7b70c17814a5c76ecd029685050d344745ba05870e587d59";30const EXPECTED_PROOF =31  "39efee52ccc9d7eaa24fcfec9a4c75eaad75a6bf3319d9794d9227f2b1466752";3233function derivePublic(privateKey: Uint8Array): Uint8Array {34  const pair = x25519GenerateKeyPair();35  // We can't derive a public from an arbitrary private with @stablelib's36  // generateKeyPair (it samples a fresh secret). For the cross-check, the37  // expected public keys are pinned above so we just use them directly.38  void pair;39  throw new Error("derivePublic should not be called — use pinned constants");40}4142describe("noise-js cross-check", () => {43  it("computes the same proof bytes as the Rust auth.rs HMAC-SHA256 scheme", () => {44    // Use the pinned public-key constants — they correspond to the X2551945    // public derived from the all-0x01 / all-0x02 private keys. Rederiving46    // them here would require a "derivePublic from raw scalar" helper that47    // @stablelib does not expose, so we trust the Rust pinned values.48    void derivePublic;4950    const initiatorPublic = hexToBytes(EXPECTED_INITIATOR_PUBLIC);51    const responderPublic = hexToBytes(EXPECTED_RESPONDER_PUBLIC);5253    const proof = computeAuthProof(54      INITIATOR_PRIVATE,55      initiatorPublic,56      responderPublic,57      NONCE,58    );5960    expect(bytesToHex(proof)).toBe(EXPECTED_PROOF);61  });62});6364function hexToBytes(hex: string): Uint8Array {65  const out = new Uint8Array(hex.length / 2);66  for (let i = 0; i < hex.length; i += 2) {67    out[i / 2] = parseInt(hex.slice(i, i + 2), 16);68  }69  return out;70}