pqcrypto 0.3.0
pqcrypto: ^0.3.0 copied to clipboard
Pure Dart post-quantum cryptography library with FIPS 203-aligned ML-KEM and experimental ML-DSA APIs. Flutter and Web compatible.
Changelog #
Unreleased #
0.3.0 #
Added #
- Project-level Universal Multi-Agent PQC Framework setup:
- canonical framework guide in
doc/UNIVERSAL_MULTI_AGENT_PQC_FRAMEWORK.md; - machine-readable manifest in
tool/agent_framework/pqc_framework.yaml; - native thin wrappers for Codex, Claude Code, and Antigravity.
- canonical framework guide in
example/main.dartnow demonstrates ML-KEM shared-secret agreement, ML-DSA signing/verification, and an ML-DSA-signed ML-KEM-768 handshake transcript.doc/SERVERPOD_FLUTTER_GUIDE.mdnow covers ML-KEM + ML-DSA Serverpod/Flutter integration, strict byte contracts, generated model sketches, Flutter isolate guidance, and framework-driven implementation prompts.- ML-DSA (FIPS 204) is now byte-exact against the official KAT corpus for
ML-DSA-44, ML-DSA-65, and ML-DSA-87 across the full matrix of signing mode
(
deterministic,hedged) × implementation flavour (raw/internal,pure/external-with-context,hashed/HashML-DSA): 300/300 key generations and 1800/1800 signatures reproduced byte-for-byte, all verifying. - External FIPS 204 API on
MlDsa:generateKeyPair(params)(fresh randomness),sign/verifywith a context string (≤ 255 bytes) and hedged-by-default signing,signDeterministic, and the internal/CAVP helpersgenerateKeyPairSeeded,signInternal,verifyInternal. - HashML-DSA (
hashSign/hashVerify) with the FIPS 204 §5.4 pre-hash: SHA-256 (ML-DSA-44), SHA-384 (ML-DSA-65), SHA-512 (ML-DSA-87), with DER OID domain separation. - Vendored FIPS 180-4 SHA-2 (
lib/src/common/sha2.dart): SHA-256/384/512, web-safe 64-bit (hi/lo pair) arithmetic, pinned by direct NIST vectors. - Repo-local ML-DSA KAT corpus under
test/data/MLDSA(18.rspfiles) with a discovered, deterministic runnertest/mldsa_kat_test.dart; ML-KEM corpus moved totest/data/MLKEM. - New focused tests: Appendix B zetas + negacyclic NTT property, rounding
boundary cases, malformed-input/negative verification, external-API behavior,
and direct SHA-2 vectors. All run on the VM,
dart2js, anddart2wasm. SECURITY.md(vulnerability reporting / coordinated disclosure policy) anddoc/FIPS_140_BOUNDARY.md(why algorithm conformance is not CMVP/FIPS 140 module validation), linked from every place the claim boundary is raised.
Changed #
-
ML-KEM decapsulation hardening: the FIPS 203 output is now selected with a constant-time branchless mask — both
K'andJ(z || c)are always computed, so success vs. implicit-rejection no longer differs in control flow. Secret intermediates (m',K' || r',J(z || c),c',z) are zeroized in afinallyblock, and the KEM now reuses a cachedRandom.secure(). The 3000-vector ML-KEM KAT corpus (including invalid-ciphertext vectors) remains byte-exact. -
ML-DSA rejection samplers (
RejNTTPoly,RejBoundedPoly,SampleInBall) now use an incremental SHAKE XOF (KeccakXof) instead of fixed buffers, so they cannot exhaust output during normal operation. -
ML-DSA packing preserves signed coefficient domains for
s1/s2/t0/zinstead of folding negatives into[0, q-1]. -
_normExceeds(the ML-DSA norm gate) evaluates all 256 coefficients with no secret-dependent early exit, and uses only VM/web-portable arithmetic. -
Verification is total:
MlDsa.verify/verifyInternalreturnfalse(never throw) for wrong pk/sig lengths, malformed hints, or over-long context. -
DilithiumParamsexposes computed FIPS 204 Table 2 sizes (publicKeyBytes,secretKeyBytes,signatureBytes, plus per-poly sizes,lambda,securityCategory) as the single source of truth; the unusedcrhBytesconstant was removed.
Fixed #
RejBoundedPoly(ExpandS) for η=2: now accepts half-bytes< 15mapping to2 − (b mod 5)per FIPS 204, fixing the stream-consumption rate that made key generation diverge from the standard. This was the sole core defect.- ML-DSA verification no longer used a 32-bit left shift (
<< d) that overflowed ondart2js; it multiplies by2^dso web results match the VM.
Security #
- Best-effort secret zeroization (
lib/src/common/zeroize.dart) applied infinallyblocks around key generation and signing intermediates. Dart cannot guarantee hard memory erasure; seedoc/SECURITY_AUDIT.mdfor the boundary.
Notes #
- This repository continues to make no CMVP/FIPS 140 module validation claim. ML-DSA conformance evidence is the checked-in KAT corpus and regression suite.
0.2.1 #
Added #
- Expanded the OpenSSL interoperability harness from ML-KEM-768 only to ML-KEM-512, ML-KEM-768, and ML-KEM-1024.
- Added stronger OpenSSL interop checks:
- Deterministic shared-seed key generation proves byte-identical public keys.
- Public-key import/export round-trip proves raw wire encoding compatibility.
- Invalid-ciphertext implicit rejection proves
J(z || c)agreement. - Negative coverage confirms truncated OpenSSL public keys are rejected.
- Added VM + web round-trip tests so KEM keygen/encaps/decaps is exercised under
the Dart VM,
dart2js, anddart2wasm. - Added FIPS 202 SHA-3/SHAKE known-answer coverage for the vendored Keccak implementation.
Changed #
- Removed the
pointycastleruntime dependency by vendoring the FIPS 202 SHA3-256, SHA3-512, SHAKE128, and SHAKE256 implementation in-tree. - Updated the README and OpenSSL interop documentation to describe the all-parameter-set A-G interop suite, OpenSSL >= 3.5 requirement, and zero-dependency pure-Dart package boundary.
- Updated CI to include web compiler testing and the expanded OpenSSL interoperability suite.
0.2.0 #
Added #
- Input validation for
encapsulate()anddecapsulate()per FIPS 203 §7.2/§7.3:- Public key length and modulus checks (non-canonical coefficient rejection via
ByteEncode₁₂ ∘ ByteDecode₁₂round-trip). - Secret key length and embedded
H(pk)integrity check. - Ciphertext length check.
Pack.decodeSecretKeylength guard.
- Public key length and modulus checks (non-canonical coefficient rejection via
- OpenSSL interoperability tool (
tool/openssl_interop/):dart:ffi-based harness proving wire-level ML-KEM-768 compatibility with OpenSSL ≥ 3.5. Four-way test matrix (A/B/C/D) validates byte-identical shared secrets across implementations. - CI workflows:
ci.yml: format check, static analysis, and full test suite (unit + 3000-vector KAT corpus) on every push/PR.interop.yml: builds OpenSSL 4.0.0 from source (cached), runs the four interop tests on every push/PR.
- New tests:
kem_validation_test.dart: exercises all input validation paths across ML-KEM-512/768/1024.keygen_derivation_test.dart: isolates FIPS 203 domain separation (G(d || k)) and matrix expansion ordering.poly_test.dart: verifiesbarrettReducereturns canonical residues in[0, q).
- Documentation:
doc/MLKEM_TESTING.md: KAT file hashes, coverage boundaries, release-gate commands, and scoped claim boundary.doc/OPENSSL_INTEROP.md: full interop guide with FFI bindings, versions, results, and use cases.
- Test hooks
genMatrixEntryForTest/sampleNttForTestonIndcpa(internal, not exported). .pubignoreto exclude dev-only files from the published package.
Changed #
- Naming conventions: renamed internal identifiers to idiomatic Dart
lowerCamelCase(_H/_G/_J→_h/_g/_j;A_hat/t_hat/r_hat→aHat/tHat/rHat; etc.). No behavioral change. barrettReduce(): useconstfor compile-time constants and add a fallbackres %= qguard for edge-case residues.- Renamed
test/kat_evaluator.dart→test/kat_evaluator_test.dartsodart testdiscovers it automatically. - README rewritten with scoped validation claims, OpenSSL interop section, and corrected Markdown formatting.
pubspec.yamldescription: fixed typo ("Startss" → "Starts"), updated wording to "FIPS 203-aligned".
Removed #
- Unused
Poly.montgomeryReduce()(the implementation uses Barrett reduction exclusively).
0.1.0 #
- Initial release of
pqcrypto. - Implements ML-KEM (Kyber) FIPS 203 standard.
- Supports ML-KEM-512, ML-KEM-768, and ML-KEM-1024.
- Pure Dart implementation with 3000/3000 NIST KAT vectors passing.
- Compatible with Flutter and Dart Web (Wasm/JS).