kxco-pq-attest 2.0.3 → 2.0.5
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 +22 -0
- package/README.md +108 -59
- package/package.json +12 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.0.5
|
|
4
|
+
|
|
5
|
+
Documentation. No source change.
|
|
6
|
+
|
|
7
|
+
The release-integrity lines now name the version that SLSA provenance and
|
|
8
|
+
the CycloneDX SBOM start from, and the keyword list drops `quantum-safe`,
|
|
9
|
+
which was removed on purpose in an earlier release.
|
|
10
|
+
|
|
11
|
+
Every GitHub Action in CI is now pinned by commit SHA, as the page states.
|
|
12
|
+
|
|
13
|
+
## 2.0.4
|
|
14
|
+
|
|
15
|
+
Documentation. No source change.
|
|
16
|
+
|
|
17
|
+
**The npm page leads with what the package proves.** The first screen now says what a signed envelope proves, who can check it and
|
|
18
|
+
for how long, the evidence underneath it and the migration dates set by NIST,
|
|
19
|
+
Executive Order 14412, OMB M-26-15 and the UK NCSC.
|
|
20
|
+
|
|
21
|
+
A family table maps every KXCO package to the job it does, and a new For
|
|
22
|
+
institutions section sets out the operated services and how to reach us. The
|
|
23
|
+
evidence documents are unchanged and linked from the page.
|
|
24
|
+
|
|
3
25
|
## 2.0.3
|
|
4
26
|
|
|
5
27
|
Documentation. No source change.
|
package/README.md
CHANGED
|
@@ -1,40 +1,34 @@
|
|
|
1
1
|
# kxco-pq-attest
|
|
2
2
|
|
|
3
|
+
**Post-quantum document signing any counterparty can verify offline, years later, with nobody to ask.**
|
|
4
|
+
|
|
3
5
|
[](https://www.npmjs.com/package/kxco-pq-attest)
|
|
6
|
+
[](https://www.npmjs.com/package/kxco-pq-attest)
|
|
7
|
+
[](https://github.com/KnightsbridgeAIQ/kxco-post-quantum/blob/main/CONFORMANCE.md)
|
|
8
|
+
[](https://www.npmjs.com/package/kxco-pq-attest)
|
|
4
9
|
[](https://socket.dev/npm/package/kxco-pq-attest)
|
|
5
10
|
[](./LICENSE)
|
|
6
11
|
[](https://nodejs.org)
|
|
7
12
|
|
|
8
|
-
|
|
13
|
+
Signs arbitrary data (strings, Buffers, objects) with ML-DSA-65 (NIST FIPS 204) and produces a self-contained JSON envelope any counterparty can verify without trust delegation. Optionally anchors the envelope hash on Armature L1 via the KXCO relay, creating a permanent timestamped on-chain record.
|
|
9
14
|
|
|
10
|
-
|
|
15
|
+
- **Verification needs nothing from us.** `verify(envelope, publicKey)` returns from the JSON alone: no endpoint, no account and no licence, now or in ten years.
|
|
16
|
+
- **Every field is bound.** Payload, key id and issue time sit inside the signed bytes behind a version prefix, so no field can be reordered or replayed against a different timestamp.
|
|
17
|
+
- **Survives key rotation.** Each envelope names its key, so an envelope signed under a since-rotated key still verifies years later.
|
|
18
|
+
- **Time the chain itself vouches for.** Anchor on Armature L1 and the transaction hash and block number travel inside the signed message, still checkable by an air-gapped verifier.
|
|
19
|
+
- **Hybrid when a policy asks for it.** `attest(payload, keypair, { classical })` adds an Ed25519 or ECDSA-P256 co-signature over the same message, and `verifyAsync(envelope, key, { requireBoth: true })` demands both.
|
|
20
|
+
- **Three levels of proof.** `signature` and `anchored` verify offline for good; `anchored+live` adds the KXCO registry's answer that the signing key is still trusted now.
|
|
21
|
+
- **Runs where you do.** Node.js 20.19 and later, and Cloudflare Workers.
|
|
22
|
+
- **Proven underneath.** 1,793 NIST ACVP vectors passed, 0 failed, and 225 interoperability checks against liboqs, Bouncy Castle and the Python reference implementations, 0 failed, in [`kxco-post-quantum`](https://github.com/KnightsbridgeAIQ/kxco-post-quantum/blob/main/CONFORMANCE.md).
|
|
23
|
+
- **A supply chain you can check.** SLSA provenance and a CycloneDX SBOM on every release since 1.1.5, third-party dependencies pinned to exact versions, and every GitHub Action pinned by commit SHA.
|
|
11
24
|
|
|
12
|
-
|
|
25
|
+
**The migration has dates.**
|
|
26
|
+
|
|
27
|
+
- **NIST** published [FIPS 203](https://csrc.nist.gov/pubs/fips/203/final), [FIPS 204](https://csrc.nist.gov/pubs/fips/204/final) and [FIPS 205](https://csrc.nist.gov/pubs/fips/205/final) in August 2024.
|
|
28
|
+
- **United States:** [Executive Order 14412](https://www.federalregister.gov/documents/2026/06/25/2026-12909/securing-the-nation-against-advanced-cryptographic-attacks), signed on 22 June 2026, moves federal high-value and high-impact systems to post-quantum key establishment by 31 December 2030 and to post-quantum signatures by 31 December 2031. [OMB M-26-15](https://www.whitehouse.gov/wp-content/uploads/2026/06/M-26-15-Execution-of-the-Migration-to-Post-Quantum-Cryptography.pdf) requires PQC-agile libraries for all new applications.
|
|
29
|
+
- **United Kingdom:** the [NCSC](https://www.ncsc.gov.uk/guidance/pqc-migration-timelines) sets 2028, 2031 and 2035 as its migration milestones.
|
|
13
30
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
- **Provenance.** Each release carries a SLSA provenance attestation tying the
|
|
17
|
-
published tarball to the commit and workflow that built it. Verify with
|
|
18
|
-
`npm audit signatures`, or read it directly from
|
|
19
|
-
`registry.npmjs.org/-/npm/v1/attestations/kxco-pq-attest@<version>`.
|
|
20
|
-
- **Bill of materials.** A CycloneDX SBOM is published as a GitHub Release asset
|
|
21
|
-
at `releases/download/v<version>/sbom.cyclonedx.json`, a permanent
|
|
22
|
-
unauthenticated URL. Not an expiring build artifact.
|
|
23
|
-
- **Pinned where it matters.** Third-party dependencies are pinned to exact
|
|
24
|
-
versions, never ranges, so the code that performs the cryptography cannot
|
|
25
|
-
change without a release. Sibling `kxco-*` packages sit on caret ranges
|
|
26
|
-
deliberately: it means a correctness fix in the base package reaches you
|
|
27
|
-
without a release of every package above it. That is not theoretical. When
|
|
28
|
-
`@noble/post-quantum` 0.7.1 was found to fail NIST SLH-DSA verification
|
|
29
|
-
vectors, the revert in the base package propagated here on the next install.
|
|
30
|
-
Every GitHub Action is pinned by 40-character commit SHA.
|
|
31
|
-
- **Conformance underneath.** The cryptography comes from
|
|
32
|
-
[`kxco-post-quantum`](https://www.npmjs.com/package/kxco-post-quantum), which
|
|
33
|
-
is run against **2,103 NIST ACVP vectors: 1,793 passed, 0 failed, 310 skipped** and a **225-check
|
|
34
|
-
cross-implementation interoperability matrix** against liboqs, Bouncy Castle
|
|
35
|
-
and two pure-Python implementations, in both directions and with negative
|
|
36
|
-
controls. Its published tarball also rebuilds bit-for-bit from its own tag,
|
|
37
|
-
verified in CI on every run.
|
|
31
|
+
[Quick start](#quick-start) · [Envelope format](#envelope-format) · [For institutions](#for-institutions) · [Assessment notes](./ASSESSMENT.md) · [Changelog](./CHANGELOG.md) · [kxco.ai](https://kxco.ai)
|
|
38
32
|
|
|
39
33
|
## When to use this
|
|
40
34
|
|
|
@@ -71,9 +65,12 @@ const result = verify(envelope, keypair.publicKey)
|
|
|
71
65
|
|
|
72
66
|
```js
|
|
73
67
|
import { attest } from 'kxco-pq-attest'
|
|
74
|
-
import {
|
|
68
|
+
import { KxcoChain } from 'kxco-pq-chain' // Armature L1 relay client
|
|
75
69
|
|
|
76
|
-
const chain =
|
|
70
|
+
const chain = new KxcoChain({
|
|
71
|
+
identity: institutionIdentity, // a KxcoIdentity from kxco-pq-sdk
|
|
72
|
+
licenceKey: process.env.KXCO_LICENCE_KEY, // the hosted anchoring service
|
|
73
|
+
})
|
|
77
74
|
|
|
78
75
|
const envelope = await attest(
|
|
79
76
|
{ ref: 'INV-2024-0042', amount: 50000 },
|
|
@@ -83,6 +80,26 @@ const envelope = await attest(
|
|
|
83
80
|
// envelope.chainAnchor: { txHash: '0x...', blockNumber: 1234567 }
|
|
84
81
|
```
|
|
85
82
|
|
|
83
|
+
## For institutions
|
|
84
|
+
|
|
85
|
+
The cryptography is free under Apache-2.0, works offline and needs nothing from
|
|
86
|
+
KXCO, now or in ten years. What KXCO sells is the part that has to be operated:
|
|
87
|
+
an answer about the present.
|
|
88
|
+
|
|
89
|
+
| Service | What you get |
|
|
90
|
+
|---|---|
|
|
91
|
+
| Hosted key registry | Whether a key is active, revoked or rotated, answered at verification time |
|
|
92
|
+
| Meta-transaction relay | KXCO validates your signed intent, pays the gas and submits it, so you never hold a token or run a node |
|
|
93
|
+
| On-chain anchoring | A timestamp on Armature L1 that the chain itself has verified |
|
|
94
|
+
| Live revocation | `anchored+live` verification, which confirms the signing key is still trusted now |
|
|
95
|
+
| Support and SLA | Availability commitments, an escalation path and a named contact |
|
|
96
|
+
|
|
97
|
+
Priced in USD, per seat, per year. No tokens, no nodes and no wallets. The line
|
|
98
|
+
between free and paid is set out in
|
|
99
|
+
[LICENCE-PRODUCT.md](https://github.com/KnightsbridgeAIQ/kxco-post-quantum/blob/main/LICENCE-PRODUCT.md).
|
|
100
|
+
|
|
101
|
+
**Talk to us: [admin@kxco.ai](mailto:admin@kxco.ai)** · [kxco.ai](https://kxco.ai)
|
|
102
|
+
|
|
86
103
|
## API
|
|
87
104
|
|
|
88
105
|
### `attest(payload, keypair, options?)`
|
|
@@ -96,6 +113,7 @@ Signs `payload` with ML-DSA-65 and returns an envelope. Returns a Promise.
|
|
|
96
113
|
| `options.anchor` | `boolean` | Default `false`. When `true`, anchors the envelope hash on-chain. Requires `chain`. |
|
|
97
114
|
| `options.purpose` | `string` | Optional label stored with the on-chain anchor (e.g. `'trade-confirm'`). |
|
|
98
115
|
| `options.chain` | `object` | Armature L1 relay client. Required when `anchor: true`. Must implement `anchorAttestation({ payloadHash, purpose })`. |
|
|
116
|
+
| `options.classical` | `{ alg, privateKey, publicKey }` | Optional Ed25519 or ECDSA-P256 co-signature over the same message the ML-DSA-65 signature covers. Generate the pair with `generateClassicalKeypair(alg)`, which uses WebCrypto and runs in Node, Workers and browsers. |
|
|
99
117
|
|
|
100
118
|
When `anchor: true`, the envelope hash (SHA-256 of the signed JSON) is posted to the relay and the result is attached to the envelope as `chainAnchor`.
|
|
101
119
|
|
|
@@ -120,44 +138,75 @@ Verifies the ML-DSA-65 signature on an envelope. Returns synchronously.
|
|
|
120
138
|
|
|
121
139
|
`payload` is the raw bytes of the original data. For strings, decode with `new TextDecoder().decode(result.payload)`.
|
|
122
140
|
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
### `verifyAsync(envelope, publicKey, opts?)`
|
|
144
|
+
|
|
145
|
+
The full verifier, for the checks that need more than the JSON.
|
|
146
|
+
|
|
147
|
+
| Option | Type | Description |
|
|
148
|
+
|-----------|------|-------------|
|
|
149
|
+
| `opts.mode` | `'signature' \| 'anchored' \| 'anchored+live'` | `anchored+live` asks the KXCO registry whether the signing key is still trusted now, and fails closed. |
|
|
150
|
+
| `opts.requireBoth` | `boolean` | Require a valid classical co-signature as well as the ML-DSA-65 signature. |
|
|
151
|
+
| `opts.classicalPublicKey` | `Uint8Array` | Pin the classical key rather than accepting the one the envelope names. |
|
|
152
|
+
|
|
123
153
|
## Envelope format
|
|
124
154
|
|
|
125
155
|
```json
|
|
126
156
|
{
|
|
127
|
-
"kxco-attest": "
|
|
157
|
+
"kxco-attest": "2",
|
|
128
158
|
"payload": "<base64url-encoded bytes>",
|
|
159
|
+
"alg": "ML-DSA-65",
|
|
129
160
|
"kid": "<ML-DSA-65 public key fingerprint>",
|
|
130
|
-
"
|
|
131
|
-
"
|
|
132
|
-
"
|
|
161
|
+
"sig": "<base64url-encoded ML-DSA-65 signature>",
|
|
162
|
+
"issuedAt": "2026-09-29T09:32:11.000Z",
|
|
163
|
+
"chainId": 1111111,
|
|
164
|
+
"anchor": {
|
|
133
165
|
"txHash": "0xabc123...",
|
|
134
166
|
"blockNumber": 1234567
|
|
135
|
-
}
|
|
167
|
+
},
|
|
168
|
+
"verifyModeHint": "anchored"
|
|
136
169
|
}
|
|
137
170
|
```
|
|
138
171
|
|
|
139
|
-
`
|
|
140
|
-
|
|
141
|
-
The signing message is a deterministic concatenation: `kxco-attest-
|
|
172
|
+
`anchor` is present when the envelope was anchored on-chain, `chainId` when the relay confirmed the chain, and `classical` when the envelope was co-signed. The envelope is self-contained either way: `verify()` works from the JSON alone, with no external calls.
|
|
173
|
+
|
|
174
|
+
The signing message is a deterministic concatenation behind a version prefix: `kxco-attest-v2`, then the payload, algorithm, kid, issue time, chain id, anchor transaction hash and block number, and the verify-mode hint, one per line. No field can be reordered, replayed against a different timestamp or given a different anchor without invalidating the signature.
|
|
175
|
+
|
|
176
|
+
## The KXCO post-quantum family
|
|
177
|
+
|
|
178
|
+
This signs, so anyone can prove where a payload came from and that it is
|
|
179
|
+
unchanged. The rest of the family covers the jobs around it:
|
|
180
|
+
|
|
181
|
+
| You need to | Install |
|
|
182
|
+
|---|---|
|
|
183
|
+
| Put the whole stack in one install | [`kxco-pq`](https://www.npmjs.com/package/kxco-pq) |
|
|
184
|
+
| Use ML-DSA, ML-KEM and SLH-DSA directly | [`kxco-post-quantum`](https://www.npmjs.com/package/kxco-post-quantum) |
|
|
185
|
+
| Keep signing keys on the HSM you already run | [`kxco-pq-hsm`](https://www.npmjs.com/package/kxco-pq-hsm) |
|
|
186
|
+
| Sign a document or record anyone can verify offline | [`kxco-pq-attest`](https://www.npmjs.com/package/kxco-pq-attest) |
|
|
187
|
+
| Keep a tamper-evident audit trail | [`kxco-pq-audit`](https://www.npmjs.com/package/kxco-pq-audit) |
|
|
188
|
+
| Verify a signature in a browser, with no server | [`kxco-verify`](https://www.npmjs.com/package/kxco-verify) |
|
|
189
|
+
| Issue institution identity credentials | [`kxco-pq-sdk`](https://www.npmjs.com/package/kxco-pq-sdk) |
|
|
190
|
+
| Encrypt files and payloads to one or many recipients | [`kxco-pq-vault`](https://www.npmjs.com/package/kxco-pq-vault) |
|
|
191
|
+
| Encrypt Node streams and WebSockets | [`kxco-pq-tls`](https://www.npmjs.com/package/kxco-pq-tls) |
|
|
192
|
+
| Sign and verify webhooks | [`kxco-post-quantum-webhook`](https://www.npmjs.com/package/kxco-post-quantum-webhook) |
|
|
193
|
+
| Give an AI agent an identity a verified institution sponsors | [`kxco-pq-agent`](https://www.npmjs.com/package/kxco-pq-agent) |
|
|
194
|
+
| Have Armature L1 verify a signature in consensus | [`kxco-pq-chain`](https://www.npmjs.com/package/kxco-pq-chain) |
|
|
195
|
+
| Prove an envelope at three levels, offline to on-chain | [`kxco-pq-network`](https://www.npmjs.com/package/kxco-pq-network) |
|
|
196
|
+
| Generate and rotate keys from a terminal | [`kxco-pq-cli`](https://www.npmjs.com/package/kxco-pq-cli) |
|
|
197
|
+
| Find quantum-vulnerable cryptography in a dependency tree | [`kxco-pq-scan`](https://www.npmjs.com/package/kxco-pq-scan) |
|
|
198
|
+
| Fail the build when code reaches past the wrapper | [`eslint-plugin-kxco-pq`](https://www.npmjs.com/package/eslint-plugin-kxco-pq) |
|
|
142
199
|
|
|
143
|
-
##
|
|
144
|
-
|
|
145
|
-
This signs, so anyone can prove where a payload came from and that it has not
|
|
146
|
-
changed. The envelope is readable by design: a counterparty verifies it without
|
|
147
|
-
a key exchange, offline, years later.
|
|
148
|
-
|
|
149
|
-
- [`kxco-pq-vault`](https://www.npmjs.com/package/kxco-pq-vault) when the payload must be unreadable as well as provable
|
|
150
|
-
- [`kxco-pq-sdk`](https://www.npmjs.com/package/kxco-pq-sdk) to issue and verify identity credentials
|
|
151
|
-
- [`kxco-pq-hsm`](https://www.npmjs.com/package/kxco-pq-hsm) for key generation, storage and rotation in hardware
|
|
152
|
-
|
|
153
|
-
## Part of the KXCO stack
|
|
200
|
+
## Release integrity
|
|
154
201
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
202
|
+
Every release since 1.1.5 carries a SLSA provenance attestation tying the published tarball to
|
|
203
|
+
the commit and workflow that built it: verify with `npm audit signatures`, or read
|
|
204
|
+
it from `registry.npmjs.org/-/npm/v1/attestations/kxco-pq-attest@<version>`. A CycloneDX
|
|
205
|
+
SBOM is published, from v1.1.5, as a GitHub Release asset at
|
|
206
|
+
`releases/download/v<version>/sbom.cyclonedx.json`, a permanent unauthenticated
|
|
207
|
+
URL. Sibling `kxco-*` packages sit on caret ranges so a correctness fix in the
|
|
208
|
+
base package reaches you on the next install, with no release of every package
|
|
209
|
+
above it.
|
|
161
210
|
|
|
162
211
|
## Security
|
|
163
212
|
|
|
@@ -165,10 +214,10 @@ a key exchange, offline, years later.
|
|
|
165
214
|
|
|
166
215
|
Evidenced, and reproducible on your own machine:
|
|
167
216
|
|
|
168
|
-
- **
|
|
169
|
-
- **225 interoperability checks passed, 0 failed
|
|
170
|
-
- **SLSA provenance** on every
|
|
171
|
-
- **CycloneDX SBOM** published with
|
|
217
|
+
- **1,793 NIST ACVP vectors passed, 0 failed** across FIPS 203, 204 and 205, pinned by digest, per [CONFORMANCE.md](https://github.com/KnightsbridgeAIQ/kxco-post-quantum/blob/main/CONFORMANCE.md). The other 310 are pairings the library refuses as weaker than the parameter set
|
|
218
|
+
- **225 interoperability checks passed, 0 failed**, against OpenSSL 3.5, liboqs, Bouncy Castle and dilithium-py/kyber-py, in both directions
|
|
219
|
+
- **SLSA provenance** on every release since 1.1.5: verify with `npm audit signatures`
|
|
220
|
+
- **CycloneDX SBOM** published with every release since 1.1.5
|
|
172
221
|
- `npm run evidence` regenerates the whole bundle from source
|
|
173
222
|
|
|
174
223
|
Dependency audit history is recorded in [AUDIT.md](https://github.com/KnightsbridgeAIQ/kxco-post-quantum/blob/main/AUDIT.md).
|
|
@@ -183,4 +232,4 @@ Apache-2.0 © 2026 KXCO by Knightsbridge
|
|
|
183
232
|
|
|
184
233
|
## Maintainers
|
|
185
234
|
|
|
186
|
-
Shayne Heffernan and John Heffernan
|
|
235
|
+
Shayne Heffernan and John Heffernan, [KXCO by Knightsbridge](https://kxco.ai)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kxco-pq-attest",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "Post-quantum document signing
|
|
3
|
+
"version": "2.0.5",
|
|
4
|
+
"description": "Post-quantum document signing any counterparty can verify offline, years later. ML-DSA-65 (NIST FIPS 204) over any payload in a self-contained JSON envelope, with optional anchoring on Armature L1 for a timestamp the chain itself has verified.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"post-quantum",
|
|
7
7
|
"pqc",
|
|
@@ -18,7 +18,16 @@
|
|
|
18
18
|
"regulatory",
|
|
19
19
|
"identity",
|
|
20
20
|
"credential",
|
|
21
|
-
"compliance"
|
|
21
|
+
"compliance",
|
|
22
|
+
"pqc-migration",
|
|
23
|
+
"digital-signature",
|
|
24
|
+
"document-signing",
|
|
25
|
+
"e-signature",
|
|
26
|
+
"timestamping",
|
|
27
|
+
"non-repudiation",
|
|
28
|
+
"tamper-evident",
|
|
29
|
+
"audit-trail",
|
|
30
|
+
"crypto-agility"
|
|
22
31
|
],
|
|
23
32
|
"license": "Apache-2.0",
|
|
24
33
|
"author": "Shayne Heffernan and John Heffernan",
|