kxco-post-quantum 1.1.11 → 1.2.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/README.md CHANGED
@@ -1,289 +1,135 @@
1
1
  # kxco-post-quantum
2
2
 
3
- **Production-tested post-quantum cryptography patterns.** Deterministic key derivation, hybrid webhook signing, and kid fingerprinting — the integration patterns KXCO uses in production across KnightsVault, KXCO Bank, KnightsBot, The Exchequer, and Armature L1.
3
+ Post-quantum cryptography primitives for the KXCO stack.
4
4
 
5
+ [![npm](https://img.shields.io/npm/v/kxco-post-quantum)](https://www.npmjs.com/package/kxco-post-quantum)
5
6
  [![CI](https://github.com/JackKXCO/kxco-post-quantum/actions/workflows/ci.yml/badge.svg)](https://github.com/JackKXCO/kxco-post-quantum/actions/workflows/ci.yml)
6
- [![Socket](https://socket.dev/api/badge/npm/package/kxco-post-quantum)](https://socket.dev/npm/package/kxco-post-quantum)
7
- [![npm provenance](https://img.shields.io/npm/v/kxco-post-quantum?label=npm%20%E2%9C%93%20provenance)](https://www.npmjs.com/package/kxco-post-quantum)
8
7
  [![license](https://img.shields.io/badge/license-MIT-blue)](./LICENSE)
9
- [![node](https://img.shields.io/node/v/kxco-post-quantum.svg)](https://nodejs.org)
10
- [![live verifier](https://img.shields.io/website?url=https%3A%2F%2Fchain.kxco.ai%2Fwallet%2Fverify&up_message=live&up_color=brightgreen&down_message=down&down_color=red&label=production)](https://chain.kxco.ai/wallet/verify)
11
8
 
12
- ---
9
+ ML-DSA-65 (FIPS 204) and SLH-DSA-SHA2-192s (FIPS 205) signatures, ML-KEM-768 (FIPS 203) key encapsulation, and key fingerprinting utilities. Wraps [`@noble/post-quantum`](https://github.com/paulmillr/noble-post-quantum) — the NIST reference implementation. All other `kxco-pq-*` packages depend on this one.
13
10
 
14
- ## 60-second quickstart
11
+ ---
15
12
 
16
- Install the package, fetch a freshly signed test vector from the live KXCO platform, post it back to verify — **200 OK**. The same code path every production webhook runs.
13
+ ## Install
17
14
 
18
15
  ```bash
19
- # 1. Install
20
16
  npm install kxco-post-quantum
21
-
22
- # 2. Fetch a freshly signed test vector from the live KXCO platform
23
- curl -s https://chain.kxco.ai/wallet/api/verify-demo > vector.json
24
-
25
- # 3. Post it back — the server verifies HMAC + ML-DSA-65 against the live key
26
- node --input-type=module -e '
27
- import fs from "node:fs"
28
- const v = JSON.parse(fs.readFileSync("vector.json", "utf8"))
29
- const h = v.headers
30
- const res = await fetch("https://chain.kxco.ai/wallet/api/verify-demo", {
31
- method: "POST",
32
- headers: { "Content-Type": "application/json" },
33
- body: JSON.stringify({
34
- timestamp: h["X-KXCO-Timestamp"],
35
- body: v.body,
36
- hmacSecret: v.hmacSecret,
37
- hmacSig: h["X-KXCO-Signature"],
38
- pqSig: h["X-KXCO-PQ-Signature"].replace(/^ml-dsa-65=/, ""),
39
- pqKid: h["X-KXCO-PQ-Kid"],
40
- }),
41
- })
42
- console.log(res.status, await res.json())
43
- '
44
- # → 200 { kidMatch: true, hmac: { ok: true }, pq: { ok: true }, ... }
45
- ```
46
-
47
- The platform signs every fetch fresh — no cached fixtures, no replay. `verify-demo` exposes the HMAC secret for the demo only; in production the HMAC secret never leaves the receiving server.
48
-
49
- ## Used in production at
50
-
51
- This is not a sample library. It runs in production at KXCO across multiple products. You can verify this yourself without any cooperation from us:
52
-
53
- ```bash
54
- # Fetch the live platform PQ identity key from production
55
- curl https://chain.kxco.ai/wallet/api/.well-known/kxco-pq-pubkey
56
-
57
- # Returns a JSON document with alg=ML-DSA-65, the public key (3904 hex chars),
58
- # and a kid fingerprint. The kid is fingerprint(publicKey) using this library.
59
17
  ```
60
18
 
61
- The wallet at `chain.kxco.ai` imports `kxco-post-quantum` directly from npm. The platform identity signing module ([src/lib/pqSigner.js in kxco-bank](https://chain.kxco.ai/wallet/dev-docs)) delegates to `mlDsa.keypairFromMaster`, `mlDsa.sign`, and `fingerprint` from this package. Every outbound webhook from the KXCO platform is signed using `webhook.signDelivery`. You can pin the kid returned above, install this library, and verify any webhook from the production fleet offline.
62
-
63
- Other KXCO products on the same package: KnightsVault (institutional custody), KnightsBot (universal trading — every order signed), The Exchequer (compliance intelligence), Armature L1 (the permissioned chain underneath everything).
64
-
65
- ## What this is
66
-
67
- A higher-level package that wraps [`@noble/post-quantum`](https://github.com/paulmillr/noble-post-quantum) — the audited, dependency-free TypeScript reference implementation of NIST's August 2024 post-quantum standards — with the integration patterns we run in production:
68
-
69
- - **Deterministic key derivation** from a master secret via HKDF-SHA-512 with domain separation
70
- - **Hybrid HMAC + ML-DSA-65 webhook signing** with non-repudiation
71
- - **Kid fingerprints** for fast key identification in delivery headers
72
- - **Replay protection** through enforced timestamp windows
73
- - **Constant-time comparisons** where it matters
74
-
75
- This package does NOT reimplement the NIST primitives. Cryptographic operations defer to `@noble/post-quantum`.
19
+ Requires Node.js 20.19+. ESM-only.
76
20
 
77
- ## What it isn't
78
-
79
- - Not a TLS library — use OpenSSL 3.5+ or BoringSSL for `X25519MLKEM768` at the edge
80
- - Not a key management service — use AWS KMS, HashiCorp Vault, or an HSM for production secret storage
81
- - Not FIPS 140-3 certified — the underlying algorithms are FIPS-standardised; the *module* is not validated
82
-
83
- ## Install
84
-
85
- ```bash
86
- npm install @kxco/post-quantum
87
- ```
88
-
89
- Requires Node.js 18+. ESM-only.
21
+ ---
90
22
 
91
23
  ## Quick start
92
24
 
93
- ### Sign a webhook
94
-
95
25
  ```js
96
- import { webhook, mlDsa, fingerprint, deriveSeed } from '@kxco/post-quantum'
97
-
98
- // Derive a stable platform identity from your master secret
99
- const KXCO_KEY_MASTER = Buffer.from(process.env.KXCO_KEY_MASTER, 'hex')
100
- const { publicKey, secretKey } = mlDsa.keypairFromMaster(KXCO_KEY_MASTER, 'platform-v1')
101
- const pqKid = fingerprint(publicKey)
102
-
103
- // On every outbound webhook
104
- const rawBody = JSON.stringify(payload)
105
- const headers = webhook.signDelivery({
106
- rawBody,
107
- hmacSecret: endpointSecret,
108
- pqSecretKey: secretKey,
109
- pqKid,
110
- event: 'payment.settled',
111
- deliveryId: jobId,
112
- })
113
-
114
- await fetch(url, { method: 'POST', headers, body: rawBody })
26
+ import { mlDsa, mlKem, slhDsa, fingerprint, kidEquals } from 'kxco-post-quantum'
27
+
28
+ // ML-DSA-65 — sign and verify
29
+ const { publicKey, secretKey } = mlDsa.keypairFromMaster(masterSecret, 'signing-v1')
30
+ const sig = mlDsa.sign(secretKey, 'hello')
31
+ const ok = mlDsa.verify(publicKey, 'hello', sig) // true
32
+
33
+ // SLH-DSA-SHA2-192s — hash-based signatures (same API shape as mlDsa)
34
+ const slh = slhDsa.keypairFromMaster(masterSecret, 'signing-v1')
35
+ const slhSig = slhDsa.sign(slh.secretKey, 'hello')
36
+ const slhOk = slhDsa.verify(slh.publicKey, 'hello', slhSig) // true
37
+
38
+ // Key fingerprint
39
+ const kid = fingerprint(publicKey) // e.g. '4a7c9e2f1b3d5680'
40
+ kidEquals(kid, kid) // true (constant-time)
41
+
42
+ // ML-KEM-768 — key encapsulation
43
+ const kemKeys = mlKem.keypairFromMaster(masterSecret, 'encryption-v1')
44
+ const { ciphertext, sharedSecret } = mlKem.encapsulate(kemKeys.publicKey)
45
+ const recovered = mlKem.decapsulate(ciphertext, kemKeys.secretKey)
46
+ // sharedSecret and recovered are the same 32 bytes
115
47
  ```
116
48
 
117
- ### Verify a webhook (receiver side)
118
-
119
- ```js
120
- import { webhook } from '@kxco/post-quantum'
121
-
122
- // Pin these from /.well-known/kxco-pq-pubkey on first integration
123
- const PINNED_KID = '4a7c9e2f1b3d5680'
124
- const PINNED_PUBKEY = Buffer.from('...3904 hex chars...', 'hex')
125
- const HMAC_SECRET = process.env.KXCO_WEBHOOK_SECRET
126
-
127
- const result = webhook.verifyDelivery({
128
- headers: req.headers,
129
- rawBody: req.rawBody, // the body bytes EXACTLY as received
130
- hmacSecret: HMAC_SECRET,
131
- pqPublicKey: PINNED_PUBKEY,
132
- pinnedKid: PINNED_KID,
133
- })
134
-
135
- if (!result.hmacOk && !result.pqOk) {
136
- return res.status(401).end()
137
- }
138
- ```
139
-
140
- ### Encapsulate to a recipient
141
-
142
- ```js
143
- import { mlKem } from '@kxco/post-quantum'
144
-
145
- // Sender side — encapsulate to the recipient's public key
146
- const { ciphertext, sharedSecret } = mlKem.encapsulate(recipientPubKey)
147
- // Use sharedSecret as an AES-256-GCM key; transmit ciphertext to the recipient
148
-
149
- // Recipient side — recover the same shared secret
150
- const recovered = mlKem.decapsulate(ciphertext, mySecretKey)
151
- ```
49
+ `masterSecret` is a `Buffer` or `Uint8Array` with at least 16 bytes of entropy (typically 32–64 bytes from an env var or KMS).
152
50
 
153
- ### Deterministic keypair from a master secret
51
+ ---
154
52
 
155
- ```js
156
- import { mlDsa, mlKem, deriveSeed } from '@kxco/post-quantum'
53
+ ## API
157
54
 
158
- const master = Buffer.from(process.env.KXCO_KEY_MASTER, 'hex')
55
+ ### `mlDsa` — ML-DSA-65 (NIST FIPS 204)
159
56
 
160
- // Two domain-separated keypairs from the same master
161
- const signing = mlDsa.keypairFromMaster(master, 'platform-signing-v1')
162
- const encryption = mlKem.keypairFromMaster(master, 'platform-encryption-v1')
57
+ | Export | Signature | Description |
58
+ |---|---|---|
59
+ | `keypairFromMaster` | `(master, info?) → { publicKey, secretKey }` | Deterministic keypair via HKDF-SHA-512. `info` defaults to `'ml-dsa-65-v1'`. |
60
+ | `sign` | `(secretKey, message) → string` | Signs a message. Returns a hex-encoded signature (6618 chars). |
61
+ | `verify` | `(publicKey, message, sigHex) → boolean` | Verifies a hex-encoded signature. Returns `false` on any failure. |
62
+ | `ml_dsa65` | raw primitive | The underlying `@noble/post-quantum` primitive, re-exported. |
163
63
 
164
- // You can also derive raw seeds for other purposes
165
- const customSeed = deriveSeed(master, 'audit-trail-anchor-v1', 32)
166
- ```
64
+ `publicKey` is 1952 bytes. `secretKey` is 4032 bytes. `message` accepts `Buffer`, `Uint8Array`, or `string`.
167
65
 
168
- ## The signed envelope
66
+ ### `slhDsa` — SLH-DSA-SHA2-192s (NIST FIPS 205)
169
67
 
170
- Both signatures cover **the exact same envelope**: `timestamp + "." + raw_body`.
68
+ Hash-based, stateless signatures. Security Category 3 (matching ML-DSA-65), but security rests only on the SHA-2 hash function — no lattice or number-theoretic assumptions. Use this as a conservative hedge alongside `mlDsa`. Tradeoff: signatures are ~5× larger (16224 vs 3309 bytes) and signing is slower.
171
69
 
172
- ```
173
- 4a7c9e2f1b3d5680.{"event":"payment.settled","amount":1000}
174
- ^^^ Unix seconds ^^^ raw body, byte-for-byte
175
- ```
70
+ | Export | Signature | Description |
71
+ |---|---|---|
72
+ | `keypairFromMaster` | `(master, info?) → { publicKey, secretKey }` | Deterministic keypair via HKDF-SHA-512. `info` defaults to `'slh-dsa-sha2-192s-v1'`. |
73
+ | `sign` | `(secretKey, message) → string` | Signs a message. Returns a hex-encoded signature (32448 chars). |
74
+ | `verify` | `(publicKey, message, sigHex) → boolean` | Verifies a hex-encoded signature. Returns `false` on any failure. |
75
+ | `slh_dsa_sha2_192s` | raw primitive | The underlying `@noble/post-quantum` primitive, re-exported. |
176
76
 
177
- This means receivers can verify either signature independently. Verifying both is defence-in-depth: HMAC blocks tampering by anyone without the shared secret, while ML-DSA-65 binds the message to the platform identity even if the HMAC secret leaks.
77
+ `publicKey` is 48 bytes. `secretKey` is 96 bytes. `message` accepts `Buffer`, `Uint8Array`, or `string`.
178
78
 
179
- ## Why hybrid (HMAC + PQ) instead of PQ-only?
79
+ ### `mlKem` — ML-KEM-768 (NIST FIPS 203)
180
80
 
181
- | Concern | HMAC-SHA-256 | ML-DSA-65 |
81
+ | Export | Signature | Description |
182
82
  |---|---|---|
183
- | Symmetric / asymmetric | Symmetric | Asymmetric |
184
- | Post-quantum secure | ✓ | ✓ |
185
- | Verify offline with shared secret | ✓ | — |
186
- | Non-repudiation | ✗ — anyone with the secret can forge | ✓ — only the holder of the private key can sign |
187
- | Library required to verify | none | a FIPS-204 library |
188
- | Signature size | 32 bytes | 3309 bytes |
189
-
190
- You get the cheap-and-easy verification path AND cryptographic identity binding. Receivers can adopt one signature first and the other later, or both from day one.
83
+ | `keypairFromMaster` | `(master, info?) → { publicKey, secretKey }` | Deterministic keypair via HKDF-SHA-512. `info` defaults to `'ml-kem-768-v1'`. |
84
+ | `encapsulate` | `(publicKey) → { ciphertext, sharedSecret }` | Generates a shared secret and ciphertext to send to the key holder. |
85
+ | `decapsulate` | `(ciphertext, secretKey) → Buffer` | Recovers the shared secret from a ciphertext. Returns 32 bytes. |
86
+ | `ml_kem768` | raw primitive | The underlying `@noble/post-quantum` primitive, re-exported. |
191
87
 
192
- ## API
88
+ `publicKey` is 1184 bytes. `ciphertext` is 1088 bytes. `sharedSecret` is 32 bytes.
193
89
 
194
- ### `mlDsa` — ML-DSA-65 (NIST FIPS 204, Dilithium3)
90
+ ### `fingerprint(publicKey)` → `string`
195
91
 
196
- - `keypairFromMaster(master, info?)` → `{ publicKey, secretKey }`
197
- - `sign(secretKey, message)` → hex string
198
- - `verify(publicKey, message, sigHex)` → boolean
199
- - `ml_dsa65` — the raw `@noble/post-quantum` primitive, re-exported
92
+ First 16 hex characters of SHA-256 of the public key. Stable for the lifetime of the key. Accepts raw bytes or a hex string.
200
93
 
201
- ### `mlKem` — ML-KEM-768 (NIST FIPS 203, Kyber768)
94
+ ### `kidEquals(a, b)` → `boolean`
202
95
 
203
- - `keypairFromMaster(master, info?)` → `{ publicKey, secretKey }`
204
- - `encapsulate(publicKey)` → `{ ciphertext, sharedSecret }`
205
- - `decapsulate(ciphertext, secretKey)` → `Buffer`
206
- - `ml_kem768` — the raw `@noble/post-quantum` primitive, re-exported
96
+ Constant-time comparison of two kid strings. Use this when comparing user-supplied input — not `===`.
207
97
 
208
98
  ### `deriveSeed(master, info, length)` → `Buffer`
209
99
 
210
- HKDF-SHA-512 derivation. Empty salt is fine when `master` has high entropy. Domain-separate via `info`.
211
-
212
- ### `fingerprint(publicKey)` → 16-hex `kid`
213
-
214
- First 16 hex characters of SHA-256 of the public key. Stable for the lifetime of the key.
215
-
216
- ### `kidEquals(a, b)` → boolean
100
+ HKDF-SHA-512 derivation. `master` must be at least 16 bytes. `info` is a required domain-separation string. Returns `length` bytes.
217
101
 
218
- Constant-time string compare. Use this when comparing user-supplied kids.
102
+ ### `webhook` — hybrid HMAC + ML-DSA-65 delivery signing
219
103
 
220
- ### `webhook` — hybrid signing utilities
104
+ Low-level helpers for the KXCO hybrid webhook pattern: `envelope`, `hmacHex`, `verifyHmac`, `pqSign`, `verifyPq`, `signDelivery`, `verifyDelivery`. HMAC-SHA-256 gives symmetric verification with no library dependency; ML-DSA-65 adds non-repudiation over the same `${timestamp}.${body}` envelope. The full identity/credential surface lives in `kxco-pq-sdk`.
221
105
 
222
- - `envelope(timestamp, rawBody)` → `Buffer`
223
- - `hmacHex(secret, timestamp, rawBody)` → hex string
224
- - `verifyHmac(secret, timestamp, rawBody, sigHeader)` → boolean
225
- - `pqSign(secretKey, timestamp, rawBody)` → `ml-dsa-65=<hex>` header value
226
- - `verifyPq(publicKey, timestamp, rawBody, sigHeader)` → boolean
227
- - `signDelivery({ rawBody, hmacSecret, pqSecretKey, pqKid, ... })` → header map
228
- - `verifyDelivery({ headers, rawBody, hmacSecret?, pqPublicKey?, pinnedKid?, windowSeconds? })` → `{ hmacOk, pqOk, timestampOk, kidOk }`
229
-
230
- ## Security notes
231
-
232
- - **Keep your master secret in environment variables or a KMS / HSM.** Never commit it.
233
- - **Use domain separation.** Two purposes = two distinct `info` strings.
234
- - **Pin the kid.** Don't trust the public key on every request — fetch and pin it once.
235
- - **Receive raw bodies byte-for-byte.** Re-stringifying JSON before verifying changes the signature input.
236
- - **Enforce timestamp windows.** Defaults to 5 minutes. Set lower for higher-security paths.
237
- - **Constant-time compare strings.** Use `kidEquals` and `verifyHmac`, not `===`.
238
-
239
- ## Reproducibility
240
-
241
- Every public output is pinned in `test/vectors.json`. Run them:
106
+ ---
242
107
 
243
- ```bash
244
- git clone https://github.com/JackKXCO/kxco-post-quantum
245
- cd kxco-post-quantum
246
- npm install
247
- npm test # 9 functional tests + 29 vector checks
248
- npm run test:vectors # vectors only
249
- ```
108
+ ## What this does NOT do
250
109
 
251
- Expected output: `✓ All 29 checks pass — library output matches pinned vectors bit-for-bit.`
110
+ - No identity credentials or verifiable claims (those are in `kxco-pq-sdk`)
111
+ - No relay, transport, or network layer
112
+ - No key storage or KMS integration
113
+ - No FIPS 140-3 module validation (the algorithms are FIPS-standardised; the module is not validated)
252
114
 
253
- If any check fails on a release version, file an issue. The vectors are the tripwire for cryptographic regressions.
115
+ ---
254
116
 
255
- ## Audit posture
117
+ ## Part of the KXCO stack
256
118
 
257
- See [AUDIT.md](./AUDIT.md) for the full statement. Short version:
119
+ `kxco-post-quantum` is the primitive layer. Everything else builds on it:
258
120
 
259
- - **Underlying primitives** (`@noble/post-quantum@0.2.1`) — audited by Cure53, 2024
260
- - **This wrapper** — no third-party audit yet. Roadmap: external audit Q3 2026, public bug bounty Q4 2026, FIPS 140-3 CMVP application 2027
261
- - **Internal review** — KXCO Engineering + Cybersecurity (lead: Sean O'Coiligh, ex-DTCC Offensive Cyber)
262
- - **Production deployment** — live at chain.kxco.ai since 2025-11
121
+ - **`kxco-pq-sdk`** — identity credentials, webhook signing, verifiable claims
122
+ - Other `kxco-pq-*` packages — domain-specific integrations
263
123
 
264
- ## References
124
+ Install this package directly when you need ML-DSA or ML-KEM without the rest of the identity stack.
265
125
 
266
- - [NIST FIPS 204 — Module-Lattice-Based Digital Signature Standard](https://csrc.nist.gov/pubs/fips/204/final)
267
- - [NIST FIPS 203 — Module-Lattice-Based Key-Encapsulation Mechanism Standard](https://csrc.nist.gov/pubs/fips/203/final)
268
- - [NSA CNSA 2.0](https://media.defense.gov/2022/Sep/07/2003071834/-1/-1/0/CSA_CNSA_2.0_ALGORITHMS_.PDF)
269
- - [`@noble/post-quantum`](https://github.com/paulmillr/noble-post-quantum) — the underlying audited implementation
270
- - [RFC 9106 — Argon2](https://datatracker.ietf.org/doc/html/rfc9106)
126
+ ---
271
127
 
272
128
  ## Security
273
129
 
274
- Cryptographic primitives are provided by [`@noble/post-quantum`](https://github.com/paulmillr/noble-post-quantum) and [`@noble/hashes`](https://github.com/paulmillr/noble-hashes) — independently audited by Cure53 (2024). This package does not reimplement any NIST primitive; all ML-DSA-65 and ML-KEM-768 operations delegate entirely to the audited upstream.
275
-
276
- To report a vulnerability, open a [private security advisory](https://github.com/JackKXCO/kxco-post-quantum/security/advisories/new) or email **security@kxco.ai**.
277
-
278
- ## Funding
279
-
280
- Maintained by **Shayne Heffernan** and **John Heffernan** at [KXCO by Knightsbridge](https://kxco.ai).
130
+ Cryptographic operations delegate entirely to [`@noble/post-quantum`](https://github.com/paulmillr/noble-post-quantum) and [`@noble/hashes`](https://github.com/paulmillr/noble-hashes), audited by Cure53 (2024). This package does not reimplement any NIST primitive.
281
131
 
282
- [Knightsbridge Law](https://knightsbridge.law) · [target150.com](https://target150.com) · [livetradingnews.com](https://livetradingnews.com)
283
-
284
- ## About KXCO
285
-
286
- KXCO by Knightsbridge is the unification layer for global trade — settlement, issuance, compliance, custody, trading. Quantum-resistant by design. Visit [kxco.ai](https://kxco.ai).
132
+ To report a vulnerability: [open a private security advisory](https://github.com/JackKXCO/kxco-post-quantum/security/advisories/new) or email **security@kxco.ai**.
287
133
 
288
134
  ## License
289
135
 
@@ -291,6 +137,4 @@ MIT. See [LICENSE](./LICENSE).
291
137
 
292
138
  ## Maintainers
293
139
 
294
- Shayne Heffernan · John Heffernan — [KXCO by Knightsbridge](https://kxco.ai)
295
-
296
- Deployed in production at [target150.com](https://target150.com), [knightsbridgelaw.com](https://knightsbridgelaw.com), [livetradingnews.com](https://livetradingnews.com).
140
+ Shayne Heffernan and John Heffernan — [KXCO by Knightsbridge](https://kxco.ai)
package/SECURITY.md CHANGED
@@ -1,27 +1,28 @@
1
- # Security Policy
2
-
3
- ## Reporting a vulnerability
4
- Email **security@kxco.ai**. Do not open public issues for security reports.
5
- PGP key available on request. We respond within 48 hours and credit reporters
6
- in `CHANGELOG.md` unless they request otherwise.
7
-
8
- ## Scope
9
- In scope:
10
- - Cryptographic correctness of the wrappers in this package
11
- - Constant-time guarantees on signature/HMAC comparison
12
- - Replay-window enforcement in `webhook.verify`
13
- - HKDF domain separation in `derive`
14
- - Kid fingerprint collision behaviour
15
-
16
- Out of scope (report upstream to https://github.com/paulmillr/noble-post-quantum):
17
- - Bugs in the underlying ML-DSA-65, ML-KEM-768, or HKDF primitives
18
-
19
- ## Algorithms used
20
- - ML-DSA-65 — NIST FIPS 204 (lattice signatures)
21
- - ML-KEM-768 — NIST FIPS 203 (key encapsulation)
22
- - HMAC-SHA-256
23
- - HKDF-SHA-512 (RFC 5869)
24
-
25
- ## Disclosure
26
- We follow coordinated disclosure with a 90-day default window.
27
- For actively-exploited issues we ship a patch release within 48 hours.
1
+ # Security Policy
2
+
3
+ ## Reporting a vulnerability
4
+ Email **security@kxco.ai**. Do not open public issues for security reports.
5
+ PGP key available on request. We respond within 48 hours and credit reporters
6
+ in `CHANGELOG.md` unless they request otherwise.
7
+
8
+ ## Scope
9
+ In scope:
10
+ - Cryptographic correctness of the wrappers in this package
11
+ - Constant-time guarantees on signature/HMAC comparison
12
+ - Replay-window enforcement in `webhook.verify`
13
+ - HKDF domain separation in `derive`
14
+ - Kid fingerprint collision behaviour
15
+
16
+ Out of scope (report upstream to https://github.com/paulmillr/noble-post-quantum):
17
+ - Bugs in the underlying ML-DSA-65, ML-KEM-768, SLH-DSA-SHA2-192s, or HKDF primitives
18
+
19
+ ## Algorithms used
20
+ - ML-DSA-65 — NIST FIPS 204 (lattice signatures)
21
+ - ML-KEM-768 — NIST FIPS 203 (key encapsulation)
22
+ - SLH-DSA-SHA2-192s — NIST FIPS 205 (hash-based signatures)
23
+ - HMAC-SHA-256
24
+ - HKDF-SHA-512 (RFC 5869)
25
+
26
+ ## Disclosure
27
+ We follow coordinated disclosure with a 90-day default window.
28
+ For actively-exploited issues we ship a patch release within 48 hours.
package/package.json CHANGED
@@ -1,100 +1,107 @@
1
- {
2
- "name": "kxco-post-quantum",
3
- "version": "1.1.11",
4
- "description": "Production-tested post-quantum cryptography patterns: deterministic key derivation, hybrid webhook signing, and kid fingerprinting. Built on @noble/post-quantum. Used in production at KXCO.",
5
- "keywords": [
6
- "post-quantum",
7
- "pqc",
8
- "ml-dsa",
9
- "ml-kem",
10
- "dilithium",
11
- "kyber",
12
- "nist",
13
- "fips-203",
14
- "fips-204",
15
- "webhook-signing",
16
- "quantum-resistant",
17
- "armature",
18
- "key-derivation",
19
- "hkdf",
20
- "deterministic-keys",
21
- "fingerprint",
22
- "replay-protection",
23
- "constant-time",
24
- "hybrid-signing",
25
- "non-repudiation"
26
- ],
27
- "license": "MIT",
28
- "author": "KXCO by Knightsbridge <hello@kxco.ai>",
29
- "contributors": [
30
- {
31
- "name": "Shayne Heffernan"
32
- },
33
- {
34
- "name": "John Heffernan"
35
- }
36
- ],
37
- "homepage": "https://kxco.ai",
38
- "funding": "https://kxco.ai",
39
- "repository": {
40
- "type": "git",
41
- "url": "https://github.com/JackKXCO/kxco-post-quantum.git"
42
- },
43
- "bugs": {
44
- "url": "https://github.com/JackKXCO/kxco-post-quantum/issues"
45
- },
46
- "type": "module",
47
- "sideEffects": false,
48
- "main": "./src/index.js",
49
- "types": "./src/index.d.ts",
50
- "exports": {
51
- ".": {
52
- "types": "./src/index.d.ts",
53
- "import": "./src/index.js"
54
- },
55
- "./ml-dsa": {
56
- "types": "./src/ml-dsa.d.ts",
57
- "import": "./src/ml-dsa.js"
58
- },
59
- "./ml-kem": {
60
- "types": "./src/ml-kem.d.ts",
61
- "import": "./src/ml-kem.js"
62
- },
63
- "./derive": {
64
- "types": "./src/derive.d.ts",
65
- "import": "./src/derive.js"
66
- },
67
- "./webhook": {
68
- "types": "./src/webhook.d.ts",
69
- "import": "./src/webhook.js"
70
- },
71
- "./kid": {
72
- "types": "./src/kid.d.ts",
73
- "import": "./src/kid.js"
74
- }
75
- },
76
- "files": [
77
- "src",
78
- "README.md",
79
- "LICENSE",
80
- "SECURITY.md",
81
- "CHANGELOG.md"
82
- ],
83
- "engines": {
84
- "node": ">=20.19"
85
- },
86
- "dependencies": {
87
- "@noble/hashes": "^2.2.0",
88
- "@noble/post-quantum": "^0.2.1"
89
- },
90
- "scripts": {
91
- "test": "node --test test/basic.test.js && node --test test/browser-smoke.test.js && node test/run-vectors.js",
92
- "test:vectors": "node test/run-vectors.js",
93
- "generate:vectors": "node test/generate-vectors.js > test/vectors.json",
94
- "bench": "node bench/bench.js"
95
- },
96
- "publishConfig": {
97
- "provenance": true,
98
- "access": "public"
99
- }
100
- }
1
+ {
2
+ "name": "kxco-post-quantum",
3
+ "version": "1.2.0",
4
+ "description": "ML-DSA-65, ML-KEM-768 and SLH-DSA-SHA2-192s primitives with key fingerprinting. The base layer for all kxco-pq-* packages.",
5
+ "keywords": [
6
+ "post-quantum",
7
+ "pqc",
8
+ "ml-dsa",
9
+ "ml-kem",
10
+ "slh-dsa",
11
+ "sphincs",
12
+ "dilithium",
13
+ "kyber",
14
+ "nist",
15
+ "fips-203",
16
+ "fips-204",
17
+ "fips-205",
18
+ "webhook-signing",
19
+ "quantum-resistant",
20
+ "armature",
21
+ "key-derivation",
22
+ "hkdf",
23
+ "deterministic-keys",
24
+ "fingerprint",
25
+ "replay-protection",
26
+ "constant-time",
27
+ "hybrid-signing",
28
+ "non-repudiation"
29
+ ],
30
+ "license": "MIT",
31
+ "author": "KXCO by Knightsbridge <hello@kxco.ai>",
32
+ "contributors": [
33
+ {
34
+ "name": "Shayne Heffernan"
35
+ },
36
+ {
37
+ "name": "John Heffernan"
38
+ }
39
+ ],
40
+ "homepage": "https://kxco.ai",
41
+ "funding": "https://kxco.ai",
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "https://github.com/JackKXCO/kxco-post-quantum.git"
45
+ },
46
+ "bugs": {
47
+ "url": "https://github.com/JackKXCO/kxco-post-quantum/issues"
48
+ },
49
+ "type": "module",
50
+ "sideEffects": false,
51
+ "main": "./src/index.js",
52
+ "types": "./src/index.d.ts",
53
+ "exports": {
54
+ ".": {
55
+ "types": "./src/index.d.ts",
56
+ "import": "./src/index.js"
57
+ },
58
+ "./ml-dsa": {
59
+ "types": "./src/ml-dsa.d.ts",
60
+ "import": "./src/ml-dsa.js"
61
+ },
62
+ "./ml-kem": {
63
+ "types": "./src/ml-kem.d.ts",
64
+ "import": "./src/ml-kem.js"
65
+ },
66
+ "./slh-dsa": {
67
+ "types": "./src/slh-dsa.d.ts",
68
+ "import": "./src/slh-dsa.js"
69
+ },
70
+ "./derive": {
71
+ "types": "./src/derive.d.ts",
72
+ "import": "./src/derive.js"
73
+ },
74
+ "./webhook": {
75
+ "types": "./src/webhook.d.ts",
76
+ "import": "./src/webhook.js"
77
+ },
78
+ "./kid": {
79
+ "types": "./src/kid.d.ts",
80
+ "import": "./src/kid.js"
81
+ }
82
+ },
83
+ "files": [
84
+ "src",
85
+ "README.md",
86
+ "LICENSE",
87
+ "SECURITY.md",
88
+ "CHANGELOG.md"
89
+ ],
90
+ "engines": {
91
+ "node": ">=20.19"
92
+ },
93
+ "dependencies": {
94
+ "@noble/hashes": "^2.2.0",
95
+ "@noble/post-quantum": "^0.6.1"
96
+ },
97
+ "scripts": {
98
+ "test": "node --test test/basic.test.js && node --test test/browser-smoke.test.js && node test/run-vectors.js",
99
+ "test:vectors": "node test/run-vectors.js",
100
+ "generate:vectors": "node test/generate-vectors.js > test/vectors.json",
101
+ "bench": "node bench/bench.js"
102
+ },
103
+ "publishConfig": {
104
+ "provenance": true,
105
+ "access": "public"
106
+ }
107
+ }