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/CHANGELOG.md +241 -209
- package/README.md +78 -234
- package/SECURITY.md +28 -27
- package/package.json +107 -100
- package/src/derive.d.ts +20 -20
- package/src/derive.js +47 -47
- package/src/index.d.ts +8 -7
- package/src/index.js +1 -0
- package/src/kid.d.ts +21 -21
- package/src/kid.js +53 -53
- package/src/ml-dsa.d.ts +45 -45
- package/src/ml-dsa.js +78 -78
- package/src/ml-kem.d.ts +49 -49
- package/src/ml-kem.js +61 -61
- package/src/slh-dsa.d.ts +46 -0
- package/src/slh-dsa.js +88 -0
- package/src/webhook.d.ts +119 -119
- package/src/webhook.js +135 -135
package/README.md
CHANGED
|
@@ -1,289 +1,135 @@
|
|
|
1
1
|
# kxco-post-quantum
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Post-quantum cryptography primitives for the KXCO stack.
|
|
4
4
|
|
|
5
|
+
[](https://www.npmjs.com/package/kxco-post-quantum)
|
|
5
6
|
[](https://github.com/JackKXCO/kxco-post-quantum/actions/workflows/ci.yml)
|
|
6
|
-
[](https://socket.dev/npm/package/kxco-post-quantum)
|
|
7
|
-
[](https://www.npmjs.com/package/kxco-post-quantum)
|
|
8
7
|
[](./LICENSE)
|
|
9
|
-
[](https://nodejs.org)
|
|
10
|
-
[](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
|
-
|
|
11
|
+
---
|
|
15
12
|
|
|
16
|
-
Install
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
97
|
-
|
|
98
|
-
//
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
//
|
|
104
|
-
const
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
-
|
|
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
|
-
|
|
51
|
+
---
|
|
154
52
|
|
|
155
|
-
|
|
156
|
-
import { mlDsa, mlKem, deriveSeed } from '@kxco/post-quantum'
|
|
53
|
+
## API
|
|
157
54
|
|
|
158
|
-
|
|
55
|
+
### `mlDsa` — ML-DSA-65 (NIST FIPS 204)
|
|
159
56
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
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
|
-
|
|
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
|
-
|
|
66
|
+
### `slhDsa` — SLH-DSA-SHA2-192s (NIST FIPS 205)
|
|
169
67
|
|
|
170
|
-
|
|
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
|
-
|
|
174
|
-
|
|
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
|
-
|
|
77
|
+
`publicKey` is 48 bytes. `secretKey` is 96 bytes. `message` accepts `Buffer`, `Uint8Array`, or `string`.
|
|
178
78
|
|
|
179
|
-
|
|
79
|
+
### `mlKem` — ML-KEM-768 (NIST FIPS 203)
|
|
180
80
|
|
|
181
|
-
|
|
|
81
|
+
| Export | Signature | Description |
|
|
182
82
|
|---|---|---|
|
|
183
|
-
|
|
|
184
|
-
|
|
|
185
|
-
|
|
|
186
|
-
|
|
|
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
|
-
|
|
88
|
+
`publicKey` is 1184 bytes. `ciphertext` is 1088 bytes. `sharedSecret` is 32 bytes.
|
|
193
89
|
|
|
194
|
-
### `
|
|
90
|
+
### `fingerprint(publicKey)` → `string`
|
|
195
91
|
|
|
196
|
-
-
|
|
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
|
-
### `
|
|
94
|
+
### `kidEquals(a, b)` → `boolean`
|
|
202
95
|
|
|
203
|
-
-
|
|
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.
|
|
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
|
-
|
|
102
|
+
### `webhook` — hybrid HMAC + ML-DSA-65 delivery signing
|
|
219
103
|
|
|
220
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
115
|
+
---
|
|
254
116
|
|
|
255
|
-
##
|
|
117
|
+
## Part of the KXCO stack
|
|
256
118
|
|
|
257
|
-
|
|
119
|
+
`kxco-post-quantum` is the primitive layer. Everything else builds on it:
|
|
258
120
|
|
|
259
|
-
-
|
|
260
|
-
-
|
|
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
|
-
|
|
124
|
+
Install this package directly when you need ML-DSA or ML-KEM without the rest of the identity stack.
|
|
265
125
|
|
|
266
|
-
|
|
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
|
|
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
|
-
[
|
|
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
|
|
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
|
-
-
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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.
|
|
4
|
-
"description": "
|
|
5
|
-
"keywords": [
|
|
6
|
-
"post-quantum",
|
|
7
|
-
"pqc",
|
|
8
|
-
"ml-dsa",
|
|
9
|
-
"ml-kem",
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
{
|
|
34
|
-
"name": "
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"url": "https://github.com/JackKXCO/kxco-post-quantum
|
|
45
|
-
},
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
"
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
"
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
"
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
"
|
|
88
|
-
"
|
|
89
|
-
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
"
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
"
|
|
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
|
+
}
|