kxco-post-quantum 1.3.0 → 1.4.0

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