Files
Lux Industries Inc 3b6050a4ad feat: canonical PQ profile and proof-policy identifiers v0.1.0
Single source of truth across Go / Solidity / TypeScript for the IDs
that the strict-PQ profile gate consumes. Resolves drift between:

  - papers/pq/pq.tex          STARK_FRI_SHA3_PQ (prose)
  - teleport/contracts        ProofPolicySTARKFRISHA3PQ (deployed)
  - teleport/mpc              POLICY_ID map
  - luxfi/node quasar         Go duplicates

Three subpackages, one set of strings:
  go/                    github.com/luxfi/pq-profile-ids/go
  solidity/              @luxfi/pq-profile-ids  (PQProfileIDs library
                                                 + OnlyStrictPQ modifier)
  ts/                    @luxfi/pq-profile-ids-ts

Cross-language KAT in KAT.md; all three test suites re-derive each
pinned constant from its canonical UTF-8 input.

Decomplected: this repo ONLY pins IDs and exposes the policy-gate.
It does NOT verify proofs. The verifier verifies; the gate decides
admissibility.

Tests: Go 5/5 pass, Solidity 12/12 pass, TS 8/8 pass.
2026-05-13 13:43:38 -07:00

106 lines
3.5 KiB
TypeScript

/**
* KAT + behavioural test for @luxfi/pq-profile-ids/ts.
*
* Re-derives every pinned bytes32 from its canonical UTF-8 input string
* using @noble/hashes' keccak256 so a typo in the pinned hex can never
* ship. Mirrors the Go test (`profile_test.go`) and the Solidity test
* (`PQProfileIDs.t.sol`).
*/
import { keccak_256 } from '@noble/hashes/sha3';
import {
POLICY_GROTH16_BN254,
POLICY_GROTH16_BN254_STRING,
POLICY_KZG_BLS12381,
POLICY_KZG_BLS12381_STRING,
POLICY_MLDSA65_FIPS204,
POLICY_MLDSA65_FIPS204_STRING,
POLICY_PLONK_BN254,
POLICY_PLONK_BN254_STRING,
POLICY_STARK_FRI_SHA3_PQ,
POLICY_STARK_FRI_SHA3_PQ_STRING,
PROFILE_CLASSICAL_COMPAT,
PROFILE_CLASSICAL_COMPAT_STRING,
PROFILE_HYBRID,
PROFILE_HYBRID_STRING,
PROFILE_QUASAR_STRICT_PQ,
PROFILE_QUASAR_STRICT_PQ_STRING,
SCHEME_CORONA_R_LWE,
SCHEME_DOUBLE_LATTICE,
SCHEME_ECDSA_GG18,
SCHEME_PULSAR_M_LWE,
UnknownProfileError,
VerifierRefusedUnderStrictPQError,
isPQScheme,
refuseUnderStrictPQ,
} from '../src/profile';
function kat(s: string): string {
return '0x' + Buffer.from(keccak_256(new TextEncoder().encode(s))).toString('hex');
}
describe('pq-profile-ids — KAT', () => {
it('profile IDs match keccak256(<input string>)', () => {
expect(kat(PROFILE_CLASSICAL_COMPAT_STRING)).toBe(PROFILE_CLASSICAL_COMPAT);
expect(kat(PROFILE_QUASAR_STRICT_PQ_STRING)).toBe(PROFILE_QUASAR_STRICT_PQ);
expect(kat(PROFILE_HYBRID_STRING)).toBe(PROFILE_HYBRID);
});
it('policy IDs match keccak256(<input string>)', () => {
expect(kat(POLICY_GROTH16_BN254_STRING)).toBe(POLICY_GROTH16_BN254);
expect(kat(POLICY_PLONK_BN254_STRING)).toBe(POLICY_PLONK_BN254);
expect(kat(POLICY_KZG_BLS12381_STRING)).toBe(POLICY_KZG_BLS12381);
expect(kat(POLICY_STARK_FRI_SHA3_PQ_STRING)).toBe(POLICY_STARK_FRI_SHA3_PQ);
expect(kat(POLICY_MLDSA65_FIPS204_STRING)).toBe(POLICY_MLDSA65_FIPS204);
});
});
describe('pq-profile-ids — refuseUnderStrictPQ', () => {
it('classical-compat allows every policy', () => {
for (const p of [
POLICY_GROTH16_BN254,
POLICY_PLONK_BN254,
POLICY_KZG_BLS12381,
POLICY_STARK_FRI_SHA3_PQ,
POLICY_MLDSA65_FIPS204,
]) {
expect(() => refuseUnderStrictPQ(PROFILE_CLASSICAL_COMPAT, p)).not.toThrow();
}
});
it('strict-PQ refuses BN254 / BLS family', () => {
for (const p of [POLICY_GROTH16_BN254, POLICY_PLONK_BN254, POLICY_KZG_BLS12381]) {
expect(() => refuseUnderStrictPQ(PROFILE_QUASAR_STRICT_PQ, p)).toThrow(
VerifierRefusedUnderStrictPQError,
);
}
});
it('strict-PQ allows STARK + ML-DSA', () => {
for (const p of [POLICY_STARK_FRI_SHA3_PQ, POLICY_MLDSA65_FIPS204]) {
expect(() => refuseUnderStrictPQ(PROFILE_QUASAR_STRICT_PQ, p)).not.toThrow();
}
});
it('unknown profile (including hybrid) rejects', () => {
expect(() => refuseUnderStrictPQ('0xdeadbeef', POLICY_STARK_FRI_SHA3_PQ)).toThrow(
UnknownProfileError,
);
expect(() => refuseUnderStrictPQ(PROFILE_HYBRID, POLICY_STARK_FRI_SHA3_PQ)).toThrow(
UnknownProfileError,
);
});
});
describe('pq-profile-ids — isPQScheme', () => {
it('accepts pulsar / corona / double-lattice', () => {
expect(isPQScheme(SCHEME_PULSAR_M_LWE)).toBe(true);
expect(isPQScheme(SCHEME_CORONA_R_LWE)).toBe(true);
expect(isPQScheme(SCHEME_DOUBLE_LATTICE)).toBe(true);
});
it('rejects classical schemes', () => {
expect(isPQScheme(SCHEME_ECDSA_GG18)).toBe(false);
expect(isPQScheme('bogus')).toBe(false);
});
});