kxco-pq-attest 2.0.1 → 2.0.2
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/ASSESSMENT.md +126 -0
- package/CHANGELOG.md +20 -0
- package/README.md +3 -3
- package/package.json +5 -3
package/ASSESSMENT.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Assessment notes
|
|
2
|
+
|
|
3
|
+
Where this package's boundary falls, what agility it has, and what constrains
|
|
4
|
+
its lifecycle.
|
|
5
|
+
|
|
6
|
+
Algorithm conformance belongs to
|
|
7
|
+
[`kxco-post-quantum`](https://www.npmjs.com/package/kxco-post-quantum) and is
|
|
8
|
+
published in that package's evidence bundle. It is referenced here, never
|
|
9
|
+
restated.
|
|
10
|
+
|
|
11
|
+
## Boundary
|
|
12
|
+
|
|
13
|
+
**What the assessed thing is.** A library that wraps a payload in a
|
|
14
|
+
self-contained JSON envelope carrying an ML-DSA-65 signature, the signer's key
|
|
15
|
+
fingerprint, an issue time and, optionally, a chain anchor.
|
|
16
|
+
|
|
17
|
+
**Operate: verification makes no network calls, and that is the product.**
|
|
18
|
+
`verify(envelope, publicKey)` returns synchronously from the JSON alone. A
|
|
19
|
+
counterparty holding the envelope and the public key needs nothing from KXCO,
|
|
20
|
+
no endpoint, no account and no cooperation. Anything that made verification
|
|
21
|
+
depend on us would undo the reason to use this.
|
|
22
|
+
|
|
23
|
+
The corollary is that trust in the key is entirely outside this package.
|
|
24
|
+
`verify` tells you the envelope was signed by the holder of the key you passed
|
|
25
|
+
in. It cannot tell you that key belongs to who you think, and it does not try.
|
|
26
|
+
[`kxco-pq-network`](https://www.npmjs.com/package/kxco-pq-network) is the
|
|
27
|
+
package that answers key identity, in three explicit levels; this one answers
|
|
28
|
+
one question and answers it offline.
|
|
29
|
+
|
|
30
|
+
**Signing binds every field, by construction.** The signed message is
|
|
31
|
+
`kxco-attest-v1\n<payloadB64>\n<kid>\n<issuedAt>`, a deterministic
|
|
32
|
+
concatenation with a version prefix. No field can be reordered, and an envelope
|
|
33
|
+
cannot be replayed against a different timestamp without invalidating the
|
|
34
|
+
signature.
|
|
35
|
+
|
|
36
|
+
**`issuedAt` is the signer's clock.** It is signed, so it cannot be altered
|
|
37
|
+
after the fact, and a signed clock is still the signer's clock. A signer who
|
|
38
|
+
sets their system time back produces a valid envelope with an earlier time.
|
|
39
|
+
Where the time matters, the independent bound is `chainAnchor`, which is
|
|
40
|
+
present only when the envelope was anchored, and the anchor is what a verifier
|
|
41
|
+
should be reading rather than the field.
|
|
42
|
+
|
|
43
|
+
**Start and update.** No release signing of its own. Published through CI with
|
|
44
|
+
npm provenance.
|
|
45
|
+
|
|
46
|
+
**Protect records.** Not this package's role: an envelope travels, it is not a
|
|
47
|
+
log. [`kxco-pq-audit`](https://www.npmjs.com/package/kxco-pq-audit) is the
|
|
48
|
+
append-only record.
|
|
49
|
+
|
|
50
|
+
**Retain history, and this package is better placed than its siblings.** The
|
|
51
|
+
envelope carries a `kid`, so a verifier holding several keys can select the
|
|
52
|
+
right one, which is what makes an envelope signed under a since-rotated key
|
|
53
|
+
still verifiable. `kxco-pq-audit` has no equivalent and cannot do this.
|
|
54
|
+
|
|
55
|
+
What is still missing is validity: nothing here records whether the key was
|
|
56
|
+
trusted at `issuedAt`, and there is no revocation. So an envelope signed by a
|
|
57
|
+
key that was later compromised verifies exactly as cleanly as one that was not.
|
|
58
|
+
For long-lived attestations the anchor is the thing that pins the signature to a
|
|
59
|
+
point in time, and the key-status question at that point in time is not
|
|
60
|
+
answered anywhere in this stack.
|
|
61
|
+
|
|
62
|
+
## Agility
|
|
63
|
+
|
|
64
|
+
**Inherited.** Parameter sets and backends belong to `kxco-post-quantum`. See
|
|
65
|
+
that package's `AGILITY.md`.
|
|
66
|
+
|
|
67
|
+
**The addition: a version prefix inside the signed bytes.** `kxco-attest-v1`
|
|
68
|
+
is signed, not merely written alongside. A v2 envelope format is therefore
|
|
69
|
+
distinguishable from v1 by something an attacker cannot strip, which is the
|
|
70
|
+
property a format migration needs and the reason the prefix is inside the
|
|
71
|
+
signature rather than beside it.
|
|
72
|
+
|
|
73
|
+
**The limit: the algorithm is not named in the envelope.** The format carries
|
|
74
|
+
`kid` and a signature, and no algorithm identifier. A verifier resolves the
|
|
75
|
+
algorithm by knowing it is ML-DSA-65, not by reading it. Compare
|
|
76
|
+
`kxco-pq-vault`, whose header carries an explicit `algorithm:` line, and
|
|
77
|
+
`kxco-pq-tls`, whose frame sizes make the algorithm unambiguous on the wire.
|
|
78
|
+
|
|
79
|
+
That is workable while exactly one algorithm exists, and it is the field a
|
|
80
|
+
second one would need. Adding it later means a v2 format, which the version
|
|
81
|
+
prefix already allows for; the point is that the move is a release of this
|
|
82
|
+
package rather than a configuration.
|
|
83
|
+
|
|
84
|
+
## Lifecycle
|
|
85
|
+
|
|
86
|
+
**Assess `origin/main`, and know that this working tree is ahead of it.**
|
|
87
|
+
Verified 8 September 2026: `origin/main`, this checkout and npm all read 2.0.1,
|
|
88
|
+
so the published artefact does correspond to `origin/main`.
|
|
89
|
+
|
|
90
|
+
What differs is the local working branch. `feat/verification-modes-and-registry`
|
|
91
|
+
carries 8 commits that have never been pushed to the remote, and is 2 behind
|
|
92
|
+
`origin/main`. The same pattern holds in `kxco-pq-sdk`, `kxco-pq-cli` and
|
|
93
|
+
`kxco-pq`. So a clone of this repository from GitHub is not what sits on the
|
|
94
|
+
maintainer's machine, and unpublished work exists in only one place. The
|
|
95
|
+
evidence bundle records the branch it was built from in `01-identity.json`,
|
|
96
|
+
which is why that field is there.
|
|
97
|
+
|
|
98
|
+
**Supported versions.** One line moving forward, matching the family. This
|
|
99
|
+
package is at 2.x while much of the family is at 1.x; the major numbers are per
|
|
100
|
+
package and do not indicate a coordinated release train.
|
|
101
|
+
|
|
102
|
+
**Pins.** `kxco-post-quantum` is declared `^1.6.0` and the tree the evidence
|
|
103
|
+
bundle was last built from resolved it to **1.6.0**, against a current
|
|
104
|
+
primitives release of 1.7.2. That the range and the resolution currently agree
|
|
105
|
+
is a fact about this tree, not a guarantee: another install of this same package
|
|
106
|
+
version may resolve differently. `02-primitives.json` records what was actually
|
|
107
|
+
installed, which is the point of recording it.
|
|
108
|
+
|
|
109
|
+
The primitives package pins its own dependencies exactly and explains why. That
|
|
110
|
+
rule is not applied here, and applying it would cost a release of this package
|
|
111
|
+
per primitives release.
|
|
112
|
+
|
|
113
|
+
**Ceiling.** No hardware ceiling. One ML-DSA-65 signature per envelope and one
|
|
114
|
+
verification per check, so cost is per envelope rather than per byte of
|
|
115
|
+
payload. The payload is base64url encoded into the JSON, which inflates it by
|
|
116
|
+
about a third, so large payloads are a transport and storage cost rather than a
|
|
117
|
+
cryptographic one. Attest a digest instead where that matters.
|
|
118
|
+
|
|
119
|
+
**Roadmap.** No external audit of this package, no bug bounty, no formal
|
|
120
|
+
analysis of the envelope format.
|
|
121
|
+
|
|
122
|
+
## Correcting this document
|
|
123
|
+
|
|
124
|
+
Every claim here is checkable against `src/` and the envelope format in the
|
|
125
|
+
README. If one does not match, that is a defect worth reporting through the
|
|
126
|
+
repository's issues.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.0.2
|
|
4
|
+
|
|
5
|
+
Documentation and a dependency refresh. No source change.
|
|
6
|
+
|
|
7
|
+
**ASSESSMENT.md.** Where this package's boundary falls, what cryptographic
|
|
8
|
+
agility it has beyond what the primitives provide, and what constrains its
|
|
9
|
+
lifecycle. It references the `kxco-post-quantum` evidence rather than restating
|
|
10
|
+
it, because a second copy of a conformance claim invites the reader to count it
|
|
11
|
+
twice.
|
|
12
|
+
|
|
13
|
+
**`npm run evidence` now exists.** The README already told you to run it and
|
|
14
|
+
there was no such script, so the command failed for anyone who followed it.
|
|
15
|
+
The bundle records identity, this package's own tests, its SBOM, registry
|
|
16
|
+
signature verification, and the `kxco-post-quantum` version actually installed
|
|
17
|
+
rather than the range declared.
|
|
18
|
+
|
|
19
|
+
**`kxco-post-quantum` refreshed to 1.7.2**, from 1.6.0 in the previous
|
|
20
|
+
lockfile. Within the existing range, so no declared dependency changed. Tests
|
|
21
|
+
pass unchanged.
|
|
22
|
+
|
|
3
23
|
## 2.0.0
|
|
4
24
|
|
|
5
25
|
**Version 1 envelopes still verify. That is not going to change.** An archive
|
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ Every release of this package is checkable without asking us for anything.
|
|
|
30
30
|
Every GitHub Action is pinned by 40-character commit SHA.
|
|
31
31
|
- **Conformance underneath.** The cryptography comes from
|
|
32
32
|
[`kxco-post-quantum`](https://www.npmjs.com/package/kxco-post-quantum), which
|
|
33
|
-
is run against **2,103 NIST ACVP vectors
|
|
33
|
+
is run against **2,103 NIST ACVP vectors: 1,793 passed, 0 failed, 310 skipped** and a **225-check
|
|
34
34
|
cross-implementation interoperability matrix** against liboqs, Bouncy Castle
|
|
35
35
|
and two pure-Python implementations, in both directions and with negative
|
|
36
36
|
controls. Its published tarball also rebuilds bit-for-bit from its own tag,
|
|
@@ -165,8 +165,8 @@ a key exchange, offline, years later.
|
|
|
165
165
|
|
|
166
166
|
Evidenced, and reproducible on your own machine:
|
|
167
167
|
|
|
168
|
-
- **2,103 NIST ACVP vectors** across FIPS 203, 204 and 205, pinned by digest
|
|
169
|
-
- **225 interoperability checks** against OpenSSL 3.5, liboqs, Bouncy Castle and dilithium-py/kyber-py, in both directions
|
|
168
|
+
- **2,103 NIST ACVP vectors** across FIPS 203, 204 and 205, pinned by digest: 1,793 passed, 0 failed, 310 skipped, where each skip is the library refusing a pre-hash weaker than the parameter set
|
|
169
|
+
- **225 interoperability checks passed, 0 failed, 42 not applicable** against OpenSSL 3.5, liboqs, Bouncy Castle and dilithium-py/kyber-py, in both directions
|
|
170
170
|
- **SLSA provenance** on every published release — verify with `npm audit signatures`
|
|
171
171
|
- **CycloneDX SBOM** published with each release
|
|
172
172
|
- `npm run evidence` regenerates the whole bundle from source
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kxco-pq-attest",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "Post-quantum document signing and on-chain attestation. ML-DSA-65 (FIPS 204) over any payload, producing a self-contained JSON envelope a counterparty verifies offline. Anchor it on Armature L1 for a timestamped record the chain itself has verified.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"post-quantum",
|
|
@@ -52,7 +52,8 @@
|
|
|
52
52
|
"CHANGELOG.md",
|
|
53
53
|
"LICENSE",
|
|
54
54
|
"README.md",
|
|
55
|
-
"src"
|
|
55
|
+
"src",
|
|
56
|
+
"ASSESSMENT.md"
|
|
56
57
|
],
|
|
57
58
|
"engines": {
|
|
58
59
|
"node": ">=20.19"
|
|
@@ -62,7 +63,8 @@
|
|
|
62
63
|
"kxco-pq-network": "^1.0.0"
|
|
63
64
|
},
|
|
64
65
|
"scripts": {
|
|
65
|
-
"test": "node --test --test-timeout=30000 test/attest.test.js test/envelope-v2.test.js"
|
|
66
|
+
"test": "node --test --test-timeout=30000 test/attest.test.js test/envelope-v2.test.js",
|
|
67
|
+
"evidence": "node scripts/build-evidence.mjs"
|
|
66
68
|
},
|
|
67
69
|
"funding": "https://kxco.ai",
|
|
68
70
|
"publishConfig": {
|