kxco-post-quantum 1.3.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,293 +1,414 @@
1
- # Changelog
2
-
3
- ## 1.3.0 - unreleased
4
-
5
- Adds FIPS 204 / FIPS 205 context string support. Purely additive: the
6
- cryptographic surface for every existing call site is byte-for-byte unchanged,
7
- and all 39 pinned vectors still match.
8
-
9
- ### Added
10
- - **Optional `context` on `mlDsa.sign` / `mlDsa.verify`** via a trailing options
11
- object, `{ context }`. At most 255 bytes per FIPS 204 section 5.2; strings are
12
- encoded as UTF-8. A signature made under a context does not verify without it
13
- or under a different one. Closes a real incompleteness relative to FIPS 204:
14
- the library previously could not verify a counterparty's signature that used a
15
- context.
16
- - **The same option on `slhDsa.sign` / `slhDsa.verify`**, on the same terms.
17
- Added alongside ML-DSA rather than after it, because one signature module
18
- accepting an options object while its sibling silently ignored one would be a
19
- footgun.
20
- - `MAX_CONTEXT_BYTES` (255) exported from both modules.
21
- - `test/context.test.js`, 26 tests, including cross-verification against
22
- third-party ML-DSA-65 signatures produced by OpenSSL through Python
23
- `cryptography`, covering five context shapes: short, single-byte, the 255-byte
24
- maximum, binary, and multi-byte UTF-8.
25
-
26
- ### Notes
27
- - **No behaviour change without the new argument.** Omitting `opts` takes the
28
- identical code path as before. An empty context is collapsed to no context,
29
- which is what FIPS 204 specifies and what was verified empirically.
30
- - **Misuse throws rather than returning `false`.** A context over 255 bytes, a
31
- wrongly typed context, or a bare value passed where an options object belongs
32
- raises `RangeError` / `TypeError`. These are caller bugs, not failed
33
- verifications, and swallowing them would hide a signature that silently
34
- carried no domain separation. No existing call site passes the argument, so
35
- nothing can regress.
36
- - Works identically on `@noble/post-quantum` 0.6.1 and 0.7.0, verified on both,
37
- so this release is independent of the 0.7.0 upgrade.
38
-
39
- ## 1.2.1 — 2026-07-22
40
-
41
- Metadata alignment. No code changes; cryptographic surface is byte-for-byte
42
- identical to `1.2.0` (all 39 pinned vectors match).
43
-
44
- ### Changed
45
- - **License now `Apache-2.0`** in package metadata, matching the repository
46
- LICENSE. `1.2.0` was published declaring `MIT` from a pre-relicense branch;
47
- this release corrects the published license to the canonical `Apache-2.0`.
48
- - `author` set to **Shayne Heffernan and John Heffernan**.
49
- - README security note corrected: `@noble/post-quantum` was **not** in scope
50
- of Cure53's 2023 `@noble` audit (which covered `ciphers`/`curves`/`hashes`)
51
- and is maintainer self-audited — the prior "audited by Cure53 (2024)"
52
- wording was inaccurate. See `AUDIT.md`.
53
-
54
- ## 1.2.0 — 2026-07-22
55
-
56
- Adds SLH-DSA (FIPS 205) and modernises the underlying primitive engine to
57
- `@noble/post-quantum@0.6.1`. **No breaking changes for consumers** — the
58
- public API and all previously pinned outputs are byte-for-byte identical.
59
-
60
- ### Added
61
- - **`slhDsa` — SLH-DSA-SHA2-192s (NIST FIPS 205)**, exported both from the
62
- package root and the `kxco-post-quantum/slh-dsa` subpath. Hash-based,
63
- stateless signatures at Security Category 3 (matching ML-DSA-65), whose
64
- security rests only on SHA-2 — the conservative hedge alongside the
65
- lattice-based ML-DSA-65. Deterministic `keypairFromMaster(master, info?)`
66
- via the same HKDF-SHA-512 derivation, plus `sign` / `verify`. Public key
67
- 48 bytes, secret key 96 bytes, signature 16224 bytes.
68
- - Test vectors extended to pin SLH-DSA keypairs and round-trip (39 checks,
69
- up from 29).
70
-
71
- ### Changed
72
- - **`@noble/post-quantum` bumped `^0.2.1` → `^0.6.1`** — the FIPS 203/204/205
73
- final reference implementation. The engine's public API changed argument
74
- order for signature `sign`/`verify` and requires `.js` in subpath imports;
75
- both are absorbed inside this package's wrappers, so no downstream package
76
- or caller is affected.
77
- - Description and keywords updated to reflect SLH-DSA / FIPS 205 coverage.
78
-
79
- ### Verification
80
- - 11 node tests pass, 7 browser-smoke tests pass, 39 pinned vectors pass.
81
- - **Compatibility gate:** every ML-DSA-65, ML-KEM-768, HKDF, fingerprint and
82
- webhook vector pinned under `@noble/post-quantum@0.2.1` still matches
83
- bit-for-bit under `0.6.1`. Deterministic keys derived from existing KXCO
84
- master secrets — including Armature L1 identities — are unchanged.
85
-
86
- ## 1.1.6 — 2026-05-24
87
-
88
- Maintenance release. No breaking changes.
89
-
90
-
91
-
92
- ## 1.1.5 — 2026-05-24
93
-
94
- Maintenance release. No breaking changes.
95
-
96
-
97
-
98
- ## 1.1.4 — 2026-05-24
99
-
100
- Maintenance release. No breaking changes.
101
-
102
-
103
-
104
- ## 1.1.3 — 2026-05-23
105
-
106
- Maintenance release. No breaking changes.
107
-
108
-
109
- All notable changes to this project will be documented in this file.
110
-
111
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
112
- and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
113
-
114
- ## [Unreleased]
115
-
116
- ## [1.1.2] — 2026-05-22
117
-
118
- Documentation correction. No code changes; no behaviour changes; no
119
- cryptographic surface changes vs `1.1.1`.
120
-
121
- ### Fixed
122
- - **AUDIT.md** §1 previously cited a 2024 Cure53 audit of
123
- `@noble/post-quantum`. That citation was incorrect — Cure53's 2023
124
- NDS-01 audit covered `@noble/ciphers`, `@noble/curves`, and
125
- `@noble/hashes` only; the post-quantum package was not in scope. As of
126
- 2026-05-22, upstream `@noble/post-quantum` has only been self-audited
127
- by its maintainer (v0.6.1, April 2026). AUDIT.md §1 has been rewritten
128
- to reflect the actual upstream audit posture. A correction notice is
129
- included at the top of the file. Reviewers who relied on the prior
130
- citation should re-read §1 of AUDIT.md.
131
- - **CHANGELOG.md** 1.0.0 entry similarly stated "audited by Cure53,
132
- 2024" alongside the upstream pin. That sentence has been corrected
133
- in-place in this release; the substance of the 1.0.0 release is
134
- otherwise unchanged.
135
-
136
- ### Why this is a patch, not an advisory
137
- The misstatement was in documentation only. No code path, signature,
138
- key-derivation routine, or wire format depends on the cited audit. The
139
- fix is a documentation rewrite; affected installs upgrade by pulling
140
- 1.1.2. If your due-diligence pack referenced AUDIT.md from 1.0.1
141
- through 1.1.1, please refresh against 1.1.2.
142
-
143
- ## [1.1.1] — 2026-05-21
144
-
145
- Operational hardening release. No source-code changes; this is the first
146
- release published via **npm Trusted Publishing** rather than a long-lived
147
- `NPM_TOKEN`.
148
-
149
- ### Changed
150
- - `.github/workflows/publish.yml` now publishes via npm Trusted Publishing
151
- (OIDC). The `NODE_AUTH_TOKEN` / `NPM_OTP` env vars are removed; the
152
- workflow's `id-token: write` permission is the entire credential.
153
- Registered at https://www.npmjs.com/package/kxco-post-quantum/access
154
- binding `org=JackKXCO`, `repo=kxco-post-quantum`, `workflow=publish.yml`.
155
- - Repo-level `NPM_TOKEN` and `NPM_OTP` secrets removed — no long-lived
156
- credentials remain in the publishing path.
157
-
158
- ### Why this matters
159
- - Every release tarball is now signed by GitHub Actions OIDC against the
160
- exact commit being published, with no human-held secret in the loop.
161
- - No more burning recovery codes per release. The publish workflow now
162
- runs hands-free on every `v*` tag push.
163
-
164
- ## [1.1.0] — 2026-05-21
165
-
166
- Same API. Same byte-for-byte outputs (all 29 pinned vectors still match).
167
- The package now runs in **browsers** as well as Node.
168
-
169
- ### Added
170
- - Isomorphic runtime — every module works identically in modern browsers
171
- (Chromium, Firefox, Safari) and Node, served from CDNs like esm.sh
172
- with zero polyfill burden
173
- - `test/browser-smoke.test.js` runs the public API with `globalThis.Buffer`
174
- removed, asserts plain `Uint8Array` outputs and a clean hybrid-signing
175
- round trip — proves browser compatibility in CI
176
-
177
- ### Changed
178
- - HKDF-SHA-512 now sourced from `@noble/hashes/hkdf` (was `node:crypto`)
179
- - HMAC-SHA-256 now sourced from `@noble/hashes/hmac` (was `node:crypto`)
180
- - SHA-256 for kid fingerprints now sourced from `@noble/hashes/sha256`
181
- (was `node:crypto`)
182
- - Constant-time comparisons are portable byte loops (replaces
183
- `node:crypto.timingSafeEqual`) — identical security property,
184
- runs in browsers
185
- - Functions return `Buffer` on Node (when `globalThis.Buffer` is defined)
186
- and plain `Uint8Array` in browsers. **Backwards compatible** for Node
187
- callers; `Buffer extends Uint8Array` so any code accepting `Uint8Array`
188
- already works.
189
- - `engines.node` bumped to `>=20.19` to match the underlying
190
- `@noble/hashes@2` requirement (Node 18 is past EOL)
191
-
192
- ### Dependencies
193
- - Added `@noble/hashes ^2.2.0` (peer of `@noble/post-quantum`)
194
- - `@noble/post-quantum ^0.2.1` unchanged
195
-
196
- ### Verification
197
- - 9 node tests pass
198
- - 6 browser-smoke tests pass
199
- - 29 pinned vectors still match — no cryptographic surface changes,
200
- bit-for-bit identical to 1.0.3 in Node
201
-
202
- ## [1.0.3] — 2026-05-21
203
-
204
- First release ships with SLSA Level 2 provenance attestation tied to a
205
- public GitHub Actions workflow run. No cryptographic surface changes
206
- vs `1.0.2` — every diff is metadata, types, CI, and hygiene.
207
-
208
- ### Added
209
- - SLSA Level 2 provenance on every published release via GitHub Actions OIDC
210
- (`publishConfig.provenance: true`)
211
- - `.github/workflows/publish.yml` triggered by `v*` tags — runs tests then
212
- `npm publish --provenance --access public`
213
- - `.github/workflows/ci.yml` matrix over Node 18 / 20 / 22 on every push and PR
214
- - Hand-written TypeScript declarations (`.d.ts`) for all six modules; wired
215
- into `exports[*].types` so TypeScript consumers get full typings without
216
- any build step
217
- - `.github/dependabot.yml` — weekly npm + github-actions ecosystem checks
218
- - `sideEffects: false` for tree-shaking
219
- - `funding` field in `package.json`
220
- - Top-level `"types"` field in `package.json` pointing at `./src/index.d.ts`
221
-
222
- ### Changed
223
- - `package.json` `files` allowlist tightened to `["src", "README.md", "LICENSE",
224
- "SECURITY.md", "CHANGELOG.md"]` — locks down what ships to npm
225
- - `package.json` `exports` now declares per-subpath `types` + `import` keys
226
- - `SECURITY.md` rewritten in the standard short-form template with explicit
227
- in-scope / out-of-scope split delegating primitive bugs upstream to
228
- `@noble/post-quantum`
229
- - All third-party actions in workflows pinned by 40-char commit SHA, never
230
- floating tags
231
- - README badge row trimmed to four (`npm`, `license`, `Socket`, `production-live`)
232
- and a 60-second live-verify quickstart added under the title
233
-
234
- ### Security
235
- - No cryptographic code changed in this release — every change is metadata,
236
- types, CI, and documentation. Production behaviour is bit-for-bit identical
237
- to `1.0.2`.
238
-
239
- ## [1.0.2] — 2026-05-21
240
-
241
- ### Changed
242
- - Repository URL on the npm package metadata now points to
243
- `github.com/JackKXCO/kxco-post-quantum`. No code change.
244
-
245
- ## [1.0.1] — 2026-05-21
246
-
247
- ### Added
248
- - `AUDIT.md` — self-attested audit posture with roadmap (external audit
249
- Q3 2026, public bug bounty Q4 2026, FIPS 140-3 CMVP application 2027)
250
- - `test/vectors.json` — 29 deterministic test vectors pinning every primitive
251
- output bit-for-bit
252
- - `test/run-vectors.js` — runner anyone can use to verify reproducibility
253
- - `npm test` runs both the functional tests and vector verification
254
- - `npm run test:vectors` for vector check only
255
-
256
- ### Changed
257
- - `SECURITY.md` sharpened with explicit threat model and pinned upstream
258
- `@noble/post-quantum@0.2.1` integrity hash
259
- - `README.md` "Used in production at" section with file refs to chain.kxco.ai
260
-
261
- No API changes from `1.0.0`.
262
-
263
- ## [1.0.0] — 2026-05-21
264
-
265
- First stable release. Committed public API surface:
266
-
267
- - `mlDsa.keypairFromMaster(master, info—)`, `mlDsa.sign`, `mlDsa.verify`
268
- - `mlKem.keypairFromMaster(master, info—)`, `mlKem.encapsulate`, `mlKem.decapsulate`
269
- - `deriveSeed(master, info, length)`
270
- - `fingerprint(publicKey)`, `kidEquals(a, b)`
271
- - `webhook.envelope`, `webhook.hmacHex`, `webhook.verifyHmac`,
272
- `webhook.pqSign`, `webhook.verifyPq`, `webhook.signDelivery`,
273
- `webhook.verifyDelivery`
274
-
275
- Verified at release: 9/9 functional tests + 29/29 vector checks pass.
276
-
277
- Underlying primitives via `@noble/post-quantum@^0.2.1`. See `AUDIT.md` for
278
- upstream audit posture (no third-party audit of the PQ package; self-audited
279
- by maintainer at v0.6.1, April 2026). ESM-only. Node.js 18+.
280
-
281
- ## [0.1.0] — 2026-05-21
282
-
283
- Initial pre-release.
284
-
285
- [Unreleased]: https://github.com/JackKXCO/kxco-post-quantum/compare/v1.1.2...HEAD
286
- [1.1.2]: https://github.com/JackKXCO/kxco-post-quantum/compare/v1.1.1...v1.1.2
287
- [1.1.1]: https://github.com/JackKXCO/kxco-post-quantum/compare/v1.1.0...v1.1.1
288
- [1.1.0]: https://github.com/JackKXCO/kxco-post-quantum/compare/v1.0.3...v1.1.0
289
- [1.0.3]: https://github.com/JackKXCO/kxco-post-quantum/compare/v1.0.2...v1.0.3
290
- [1.0.2]: https://github.com/JackKXCO/kxco-post-quantum/compare/v1.0.1...v1.0.2
291
- [1.0.1]: https://github.com/JackKXCO/kxco-post-quantum/compare/v1.0.0...v1.0.1
292
- [1.0.0]: https://github.com/JackKXCO/kxco-post-quantum/compare/v0.1.0...v1.0.0
1
+ # Changelog
2
+
3
+ ## 1.4.1
4
+
5
+ Evidence and documentation only. **No `src/` module changed**, no export was
6
+ added or removed, and the dependency set is unchanged, so no call site can
7
+ behave differently than it did on 1.4.0.
8
+
9
+ **liboqs is now a third interop implementation.** The cross-implementation
10
+ matrix ran against two peers and now runs against three: liboqs 0.16.0 (C),
11
+ Bouncy Castle 1.85.2 (Java) and dilithium-py 1.4.0 / kyber-py 1.2.0 (Python).
12
+ **225 checks passed, 0 failed, 42 not applicable, across 38 rows**, up from
13
+ 156/0/10 across 24. The previous figures are reproduced exactly when the new
14
+ peer is excluded, so nothing about the existing evidence moved.
15
+
16
+ SLH-DSA had one peer and now has two. liboqs runs from a container built from
17
+ source at a tag pinned in `peers-lock.json`, and CI builds it, so the version
18
+ tested is the version named.
19
+
20
+ A peer that cannot do something now records as not-applicable rather than as a
21
+ disagreement. The 42 not-applicable are itemised in CONFORMANCE.md: ten from our
22
+ own hedged signing, thirty-two from two liboqs API limits.
23
+
24
+ **AUDIT.md corrections.** The reviewer checklist told anyone doing due diligence
25
+ to fetch an endpoint that returns 500. Verification now goes to Armature L1 over
26
+ public JSON-RPC, with the calldata layout documented and a named article page
27
+ for the other half of the join. Both documented commands were run verbatim
28
+ against production before publishing.
29
+
30
+ Two false claims in the same file are withdrawn. It said we pin
31
+ `@noble/post-quantum@0.6.1`, "the exact version covered by the maintainer's own
32
+ self-audit"; we ship `0.7.0`, the self-audit covers `0.6.1`, and **the version we
33
+ ship is covered by no audit at all**. It also described the dependency as
34
+ "itself audited", contradicting its own section 1.
35
+
36
+ **Supply chain.** Each release now publishes its CycloneDX SBOM as a GitHub
37
+ Release asset at `releases/download/<tag>/sbom.cyclonedx.json`, a permanent
38
+ unauthenticated URL. It was previously generated but retained only as an
39
+ expiring Actions artifact, which is not a published SBOM. The dependency policy
40
+ is now stated in SECURITY.md rather than living only in `dependabot.yml`.
41
+
42
+ ## 1.4.0
43
+
44
+ Adds the Security Category 5 parameter sets, and publishes conformance and
45
+ interoperability evidence for everything the package computes.
46
+
47
+ Additive throughout. Two new modules appear under `src/`, and no existing module,
48
+ export, default or call path changes: the dependency set is unchanged, the
49
+ default parameter sets stay at Category 3, and all 39 pinned vectors still match
50
+ bit-for-bit. Nothing here can alter the behaviour of an existing call site.
51
+
52
+ ### Added
53
+ - **`mlDsa87` (ML-DSA-87) and `mlKem1024` (ML-KEM-1024)**, Security Category 5,
54
+ as new modules with the same API as their Category 3 counterparts. Purely
55
+ additive: no existing module, export or call path changes, and the KXCO
56
+ default stays Category 3. Subpath exports `./ml-dsa-87` and `./ml-kem-1024`.
57
+ Both are exercised by the ACVP harness and the interop matrix through their
58
+ wrapper path, not only as primitives.
59
+
60
+ Default derivation info differs from the Category 3 modules
61
+ (`ml-dsa-87-v1`, `ml-kem-1024-v1`), so one master yields unrelated keys per
62
+ parameter set rather than colliding, and `test/category5.test.js` asserts that
63
+ a signature from one set does not verify under the other in either direction.
64
+
65
+ **Supporting these sets is not a CNSA 2.0 compliance claim.** CNSA 2.0 names
66
+ both, and compliance is a property of a deployment rather than of an available
67
+ function: the KXCO estate signs at Category 3, including Armature L1 from
68
+ block 0 and every issued KXCO ID, none of which these modules change. The
69
+ accurate sentence is "supports ML-DSA-87 and ML-KEM-1024". This is stated in
70
+ both module headers, both type declarations, the README, MIGRATION.md and
71
+ CONFORMANCE.md, because it is the claim most likely to drift.
72
+
73
+ Sizes, since they are the real migration cost: ML-DSA-87 public key 2592 and
74
+ signature 4627 bytes, against 1952 and 3309 at ML-DSA-65. ML-KEM-1024 public
75
+ key and ciphertext 1568 bytes each, against 1184 and 1088. The ML-KEM shared
76
+ secret stays 32 bytes at both sets, so downstream key derivation is unaffected.
77
+ - **`conformance/`, a NIST ACVP harness** for FIPS 203, 204 and 205, covering
78
+ every parameter set NIST publishes vectors for: ML-KEM-512/768/1024,
79
+ ML-DSA-44/65/87 and all twelve SLH-DSA sets. The signature sets cover the
80
+ external and internal interfaces, pure and pre-hashed, external-mu, and
81
+ deterministic and randomized signing. Vectors are pinned by upstream commit
82
+ and per-file SHA-256 in `conformance/acvp-lock.json`, so a rewritten upstream
83
+ file fails the fetch instead of quietly changing the result.
84
+ - **`conformance/interop/`, a cross-implementation matrix** against Bouncy
85
+ Castle (Java) and dilithium-py / kyber-py (Python), neither of which shares
86
+ code with our backend. Every check runs in both directions, and includes
87
+ negative controls: a tampered signature that the peer must reject, and a
88
+ corrupted ML-KEM ciphertext that must decapsulate to an unrelated secret.
89
+ Without those, a peer that always returned true would pass the whole matrix.
90
+ - **`CONFORMANCE.md`** reporting both, including what the evidence does not
91
+ cover: no side-channel claim, no FIPS 140-3 validation, no CNSA 2.0
92
+ assertion, no protocol-level encoding claim.
93
+ - **`THREAT-MODEL.md`** stating the security boundary. In particular it states
94
+ plainly that constant-time execution cannot be established from inside
95
+ JavaScript, that timing, cache and power attackers are therefore out of
96
+ scope, and what to do instead when a key needs to withstand them.
97
+ - **`MIGRATION.md`** covering the add-then-remove path off RSA or ECDSA, and
98
+ version-to-version upgrades.
99
+ - **`.github/workflows/conformance.yml`** running both harnesses on every push
100
+ and in full weekly, so the reports describe current behaviour rather than the
101
+ day someone ran them by hand. The SLH-DSA signature sets run as a separate job
102
+ because a full pass of them takes over an hour, and per-push runs subsample
103
+ with a per-group cap, which the generated report records so a subsampled run
104
+ cannot be mistaken for a full one.
105
+ - **A CycloneDX SBOM generated during publish**, from the tree that was actually
106
+ installed for the build, and attached to the release artifacts.
107
+ - Scripts: `conformance:fetch`, `conformance:acvp`, `conformance:interop`, `sbom`.
108
+
109
+ ### Notes
110
+ - **The pre-hash skips in the ACVP report are the library being stricter than
111
+ NIST's sample files, not a coverage gap.** The backend refuses a pre-hash
112
+ whose collision strength is below the parameter set's security category;
113
+ NIST's vectors pair every approved hash with every parameter set. Those cases
114
+ are counted as skipped, never as passed.
115
+ - **Hedged signing means wrapper signatures are not reproducible.** `sign` draws
116
+ fresh randomness per signature, which FIPS 204 permits and recommends, so the
117
+ byte-equality check does not apply on the wrapper path. It is asserted on the
118
+ backend path for the same parameter sets. This is reported rather than hidden.
119
+ - **Provenance:** a release published from a workstation instead of through
120
+ `publish.yml` carries no npm attestation. The Trusted Publishing binding still
121
+ names the old `JackKXCO` org after the move to `KnightsbridgeAIQ` and needs
122
+ repointing before the OIDC path can work. See the comment in `publish.yml`.
123
+
124
+ ## 1.3.0
125
+
126
+ Adds FIPS 204 / FIPS 205 context string support. Purely additive: the
127
+ cryptographic surface for every existing call site is byte-for-byte unchanged,
128
+ and all 39 pinned vectors still match.
129
+
130
+ ### Added
131
+ - **Optional `context` on `mlDsa.sign` / `mlDsa.verify`** via a trailing options
132
+ object, `{ context }`. At most 255 bytes per FIPS 204 section 5.2; strings are
133
+ encoded as UTF-8. A signature made under a context does not verify without it
134
+ or under a different one. Closes a real incompleteness relative to FIPS 204:
135
+ the library previously could not verify a counterparty's signature that used a
136
+ context.
137
+ - **The same option on `slhDsa.sign` / `slhDsa.verify`**, on the same terms.
138
+ Added alongside ML-DSA rather than after it, because one signature module
139
+ accepting an options object while its sibling silently ignored one would be a
140
+ footgun.
141
+ - `MAX_CONTEXT_BYTES` (255) exported from both modules.
142
+ - `test/context.test.js`, 26 tests, including cross-verification against
143
+ third-party ML-DSA-65 signatures produced by OpenSSL through Python
144
+ `cryptography`, covering five context shapes: short, single-byte, the 255-byte
145
+ maximum, binary, and multi-byte UTF-8.
146
+
147
+ ### Notes
148
+ - **No behaviour change without the new argument.** Omitting `opts` takes the
149
+ identical code path as before. An empty context is collapsed to no context,
150
+ which is what FIPS 204 specifies and what was verified empirically.
151
+ - **Misuse throws rather than returning `false`.** A context over 255 bytes, a
152
+ wrongly typed context, or a bare value passed where an options object belongs
153
+ raises `RangeError` / `TypeError`. These are caller bugs, not failed
154
+ verifications, and swallowing them would hide a signature that silently
155
+ carried no domain separation. No existing call site passes the argument, so
156
+ nothing can regress.
157
+ - Works identically on `@noble/post-quantum` 0.6.1 and 0.7.0, verified on both,
158
+ so this release is independent of the 0.7.0 upgrade.
159
+
160
+ ## 1.2.1 — 2026-07-22
161
+
162
+ Metadata alignment. No code changes; cryptographic surface is byte-for-byte
163
+ identical to `1.2.0` (all 39 pinned vectors match).
164
+
165
+ ### Changed
166
+ - **License now `Apache-2.0`** in package metadata, matching the repository
167
+ LICENSE. `1.2.0` was published declaring `MIT` from a pre-relicense branch;
168
+ this release corrects the published license to the canonical `Apache-2.0`.
169
+ - `author` set to **Shayne Heffernan and John Heffernan**.
170
+ - README security note corrected: `@noble/post-quantum` was **not** in scope
171
+ of Cure53's 2023 `@noble` audit (which covered `ciphers`/`curves`/`hashes`)
172
+ and is maintainer self-audited — the prior "audited by Cure53 (2024)"
173
+ wording was inaccurate. See `AUDIT.md`.
174
+
175
+ ## 1.2.0 — 2026-07-22
176
+
177
+ Adds SLH-DSA (FIPS 205) and modernises the underlying primitive engine to
178
+ `@noble/post-quantum@0.6.1`. **No breaking changes for consumers** — the
179
+ public API and all previously pinned outputs are byte-for-byte identical.
180
+
181
+ ### Added
182
+ - **`slhDsa` — SLH-DSA-SHA2-192s (NIST FIPS 205)**, exported both from the
183
+ package root and the `kxco-post-quantum/slh-dsa` subpath. Hash-based,
184
+ stateless signatures at Security Category 3 (matching ML-DSA-65), whose
185
+ security rests only on SHA-2 — the conservative hedge alongside the
186
+ lattice-based ML-DSA-65. Deterministic `keypairFromMaster(master, info?)`
187
+ via the same HKDF-SHA-512 derivation, plus `sign` / `verify`. Public key
188
+ 48 bytes, secret key 96 bytes, signature 16224 bytes.
189
+ - Test vectors extended to pin SLH-DSA keypairs and round-trip (39 checks,
190
+ up from 29).
191
+
192
+ ### Changed
193
+ - **`@noble/post-quantum` bumped `^0.2.1` → `^0.6.1`** — the FIPS 203/204/205
194
+ final reference implementation. The engine's public API changed argument
195
+ order for signature `sign`/`verify` and requires `.js` in subpath imports;
196
+ both are absorbed inside this package's wrappers, so no downstream package
197
+ or caller is affected.
198
+ - Description and keywords updated to reflect SLH-DSA / FIPS 205 coverage.
199
+
200
+ ### Verification
201
+ - 11 node tests pass, 7 browser-smoke tests pass, 39 pinned vectors pass.
202
+ - **Compatibility gate:** every ML-DSA-65, ML-KEM-768, HKDF, fingerprint and
203
+ webhook vector pinned under `@noble/post-quantum@0.2.1` still matches
204
+ bit-for-bit under `0.6.1`. Deterministic keys derived from existing KXCO
205
+ master secrets — including Armature L1 identities — are unchanged.
206
+
207
+ ## 1.1.6 — 2026-05-24
208
+
209
+ Maintenance release. No breaking changes.
210
+
211
+
212
+
213
+ ## 1.1.5 — 2026-05-24
214
+
215
+ Maintenance release. No breaking changes.
216
+
217
+
218
+
219
+ ## 1.1.4 — 2026-05-24
220
+
221
+ Maintenance release. No breaking changes.
222
+
223
+
224
+
225
+ ## 1.1.3 — 2026-05-23
226
+
227
+ Maintenance release. No breaking changes.
228
+
229
+
230
+ All notable changes to this project will be documented in this file.
231
+
232
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
233
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
234
+
235
+ ## [Unreleased]
236
+
237
+ ## [1.1.2] — 2026-05-22
238
+
239
+ Documentation correction. No code changes; no behaviour changes; no
240
+ cryptographic surface changes vs `1.1.1`.
241
+
242
+ ### Fixed
243
+ - **AUDIT.md** §1 previously cited a 2024 Cure53 audit of
244
+ `@noble/post-quantum`. That citation was incorrect — Cure53's 2023
245
+ NDS-01 audit covered `@noble/ciphers`, `@noble/curves`, and
246
+ `@noble/hashes` only; the post-quantum package was not in scope. As of
247
+ 2026-05-22, upstream `@noble/post-quantum` has only been self-audited
248
+ by its maintainer (v0.6.1, April 2026). AUDIT.md §1 has been rewritten
249
+ to reflect the actual upstream audit posture. A correction notice is
250
+ included at the top of the file. Reviewers who relied on the prior
251
+ citation should re-read §1 of AUDIT.md.
252
+ - **CHANGELOG.md** 1.0.0 entry similarly stated "audited by Cure53,
253
+ 2024" alongside the upstream pin. That sentence has been corrected
254
+ in-place in this release; the substance of the 1.0.0 release is
255
+ otherwise unchanged.
256
+
257
+ ### Why this is a patch, not an advisory
258
+ The misstatement was in documentation only. No code path, signature,
259
+ key-derivation routine, or wire format depends on the cited audit. The
260
+ fix is a documentation rewrite; affected installs upgrade by pulling
261
+ 1.1.2. If your due-diligence pack referenced AUDIT.md from 1.0.1
262
+ through 1.1.1, please refresh against 1.1.2.
263
+
264
+ ## [1.1.1] — 2026-05-21
265
+
266
+ Operational hardening release. No source-code changes; this is the first
267
+ release published via **npm Trusted Publishing** rather than a long-lived
268
+ `NPM_TOKEN`.
269
+
270
+ ### Changed
271
+ - `.github/workflows/publish.yml` now publishes via npm Trusted Publishing
272
+ (OIDC). The `NODE_AUTH_TOKEN` / `NPM_OTP` env vars are removed; the
273
+ workflow's `id-token: write` permission is the entire credential.
274
+ Registered at https://www.npmjs.com/package/kxco-post-quantum/access
275
+ binding `org=JackKXCO`, `repo=kxco-post-quantum`, `workflow=publish.yml`.
276
+ - Repo-level `NPM_TOKEN` and `NPM_OTP` secrets removed — no long-lived
277
+ credentials remain in the publishing path.
278
+
279
+ ### Why this matters
280
+ - Every release tarball is now signed by GitHub Actions OIDC against the
281
+ exact commit being published, with no human-held secret in the loop.
282
+ - No more burning recovery codes per release. The publish workflow now
283
+ runs hands-free on every `v*` tag push.
284
+
285
+ ## [1.1.0] — 2026-05-21
286
+
287
+ Same API. Same byte-for-byte outputs (all 29 pinned vectors still match).
288
+ The package now runs in **browsers** as well as Node.
289
+
290
+ ### Added
291
+ - Isomorphic runtime — every module works identically in modern browsers
292
+ (Chromium, Firefox, Safari) and Node, served from CDNs like esm.sh
293
+ with zero polyfill burden
294
+ - `test/browser-smoke.test.js` runs the public API with `globalThis.Buffer`
295
+ removed, asserts plain `Uint8Array` outputs and a clean hybrid-signing
296
+ round trip — proves browser compatibility in CI
297
+
298
+ ### Changed
299
+ - HKDF-SHA-512 now sourced from `@noble/hashes/hkdf` (was `node:crypto`)
300
+ - HMAC-SHA-256 now sourced from `@noble/hashes/hmac` (was `node:crypto`)
301
+ - SHA-256 for kid fingerprints now sourced from `@noble/hashes/sha256`
302
+ (was `node:crypto`)
303
+ - Constant-time comparisons are portable byte loops (replaces
304
+ `node:crypto.timingSafeEqual`) — identical security property,
305
+ runs in browsers
306
+ - Functions return `Buffer` on Node (when `globalThis.Buffer` is defined)
307
+ and plain `Uint8Array` in browsers. **Backwards compatible** for Node
308
+ callers; `Buffer extends Uint8Array` so any code accepting `Uint8Array`
309
+ already works.
310
+ - `engines.node` bumped to `>=20.19` to match the underlying
311
+ `@noble/hashes@2` requirement (Node 18 is past EOL)
312
+
313
+ ### Dependencies
314
+ - Added `@noble/hashes ^2.2.0` (peer of `@noble/post-quantum`)
315
+ - `@noble/post-quantum ^0.2.1` unchanged
316
+
317
+ ### Verification
318
+ - 9 node tests pass
319
+ - 6 browser-smoke tests pass
320
+ - 29 pinned vectors still match — no cryptographic surface changes,
321
+ bit-for-bit identical to 1.0.3 in Node
322
+
323
+ ## [1.0.3] — 2026-05-21
324
+
325
+ First release ships with SLSA Level 2 provenance attestation tied to a
326
+ public GitHub Actions workflow run. No cryptographic surface changes
327
+ vs `1.0.2` — every diff is metadata, types, CI, and hygiene.
328
+
329
+ ### Added
330
+ - SLSA Level 2 provenance on every published release via GitHub Actions OIDC
331
+ (`publishConfig.provenance: true`)
332
+ - `.github/workflows/publish.yml` triggered by `v*` tags — runs tests then
333
+ `npm publish --provenance --access public`
334
+ - `.github/workflows/ci.yml` matrix over Node 18 / 20 / 22 on every push and PR
335
+ - Hand-written TypeScript declarations (`.d.ts`) for all six modules; wired
336
+ into `exports[*].types` so TypeScript consumers get full typings without
337
+ any build step
338
+ - `.github/dependabot.yml` — weekly npm + github-actions ecosystem checks
339
+ - `sideEffects: false` for tree-shaking
340
+ - `funding` field in `package.json`
341
+ - Top-level `"types"` field in `package.json` pointing at `./src/index.d.ts`
342
+
343
+ ### Changed
344
+ - `package.json` `files` allowlist tightened to `["src", "README.md", "LICENSE",
345
+ "SECURITY.md", "CHANGELOG.md"]` — locks down what ships to npm
346
+ - `package.json` `exports` now declares per-subpath `types` + `import` keys
347
+ - `SECURITY.md` rewritten in the standard short-form template with explicit
348
+ in-scope / out-of-scope split delegating primitive bugs upstream to
349
+ `@noble/post-quantum`
350
+ - All third-party actions in workflows pinned by 40-char commit SHA, never
351
+ floating tags
352
+ - README badge row trimmed to four (`npm`, `license`, `Socket`, `production-live`)
353
+ and a 60-second live-verify quickstart added under the title
354
+
355
+ ### Security
356
+ - No cryptographic code changed in this release — every change is metadata,
357
+ types, CI, and documentation. Production behaviour is bit-for-bit identical
358
+ to `1.0.2`.
359
+
360
+ ## [1.0.2] — 2026-05-21
361
+
362
+ ### Changed
363
+ - Repository URL on the npm package metadata now points to
364
+ `github.com/JackKXCO/kxco-post-quantum`. No code change.
365
+
366
+ ## [1.0.1] — 2026-05-21
367
+
368
+ ### Added
369
+ - `AUDIT.md` — self-attested audit posture with roadmap (external audit
370
+ Q3 2026, public bug bounty Q4 2026, FIPS 140-3 CMVP application 2027)
371
+ - `test/vectors.json` — 29 deterministic test vectors pinning every primitive
372
+ output bit-for-bit
373
+ - `test/run-vectors.js` — runner anyone can use to verify reproducibility
374
+ - `npm test` runs both the functional tests and vector verification
375
+ - `npm run test:vectors` for vector check only
376
+
377
+ ### Changed
378
+ - `SECURITY.md` sharpened with explicit threat model and pinned upstream
379
+ `@noble/post-quantum@0.2.1` integrity hash
380
+ - `README.md` "Used in production at" section with file refs to chain.kxco.ai
381
+
382
+ No API changes from `1.0.0`.
383
+
384
+ ## [1.0.0] — 2026-05-21
385
+
386
+ First stable release. Committed public API surface:
387
+
388
+ - `mlDsa.keypairFromMaster(master, info—)`, `mlDsa.sign`, `mlDsa.verify`
389
+ - `mlKem.keypairFromMaster(master, info—)`, `mlKem.encapsulate`, `mlKem.decapsulate`
390
+ - `deriveSeed(master, info, length)`
391
+ - `fingerprint(publicKey)`, `kidEquals(a, b)`
392
+ - `webhook.envelope`, `webhook.hmacHex`, `webhook.verifyHmac`,
393
+ `webhook.pqSign`, `webhook.verifyPq`, `webhook.signDelivery`,
394
+ `webhook.verifyDelivery`
395
+
396
+ Verified at release: 9/9 functional tests + 29/29 vector checks pass.
397
+
398
+ Underlying primitives via `@noble/post-quantum@^0.2.1`. See `AUDIT.md` for
399
+ upstream audit posture (no third-party audit of the PQ package; self-audited
400
+ by maintainer at v0.6.1, April 2026). ESM-only. Node.js 18+.
401
+
402
+ ## [0.1.0] — 2026-05-21
403
+
404
+ Initial pre-release.
405
+
406
+ [Unreleased]: https://github.com/JackKXCO/kxco-post-quantum/compare/v1.1.2...HEAD
407
+ [1.1.2]: https://github.com/JackKXCO/kxco-post-quantum/compare/v1.1.1...v1.1.2
408
+ [1.1.1]: https://github.com/JackKXCO/kxco-post-quantum/compare/v1.1.0...v1.1.1
409
+ [1.1.0]: https://github.com/JackKXCO/kxco-post-quantum/compare/v1.0.3...v1.1.0
410
+ [1.0.3]: https://github.com/JackKXCO/kxco-post-quantum/compare/v1.0.2...v1.0.3
411
+ [1.0.2]: https://github.com/JackKXCO/kxco-post-quantum/compare/v1.0.1...v1.0.2
412
+ [1.0.1]: https://github.com/JackKXCO/kxco-post-quantum/compare/v1.0.0...v1.0.1
413
+ [1.0.0]: https://github.com/JackKXCO/kxco-post-quantum/compare/v0.1.0...v1.0.0
293
414
  [0.1.0]: https://github.com/JackKXCO/kxco-post-quantum/releases/tag/v0.1.0