@attestplane/attestplane 0.0.1 → 0.0.3-alpha

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.
Files changed (106) hide show
  1. package/README.md +23 -9
  2. package/dist/adapter_conformance.d.ts +46 -0
  3. package/dist/adapter_conformance.d.ts.map +1 -0
  4. package/dist/adapter_conformance.js +160 -0
  5. package/dist/adapter_conformance.js.map +1 -0
  6. package/dist/adapters/langfuse.d.ts +51 -0
  7. package/dist/adapters/langfuse.d.ts.map +1 -0
  8. package/dist/adapters/langfuse.js +157 -0
  9. package/dist/adapters/langfuse.js.map +1 -0
  10. package/dist/adapters/langsmith.d.ts +53 -0
  11. package/dist/adapters/langsmith.d.ts.map +1 -0
  12. package/dist/adapters/langsmith.js +173 -0
  13. package/dist/adapters/langsmith.js.map +1 -0
  14. package/dist/adapters.d.ts +88 -0
  15. package/dist/adapters.d.ts.map +1 -0
  16. package/dist/adapters.js +109 -0
  17. package/dist/adapters.js.map +1 -0
  18. package/dist/anchoring.d.ts +119 -0
  19. package/dist/anchoring.d.ts.map +1 -0
  20. package/dist/anchoring.js +340 -0
  21. package/dist/anchoring.js.map +1 -0
  22. package/dist/canonical.d.ts +11 -2
  23. package/dist/canonical.d.ts.map +1 -1
  24. package/dist/canonical.js +44 -31
  25. package/dist/canonical.js.map +1 -1
  26. package/dist/canonical_text.d.ts +30 -0
  27. package/dist/canonical_text.d.ts.map +1 -0
  28. package/dist/canonical_text.js +100 -0
  29. package/dist/canonical_text.js.map +1 -0
  30. package/dist/der.d.ts +55 -0
  31. package/dist/der.d.ts.map +1 -0
  32. package/dist/der.js +200 -0
  33. package/dist/der.js.map +1 -0
  34. package/dist/event_payloads.d.ts +118 -0
  35. package/dist/event_payloads.d.ts.map +1 -0
  36. package/dist/event_payloads.js +348 -0
  37. package/dist/event_payloads.js.map +1 -0
  38. package/dist/event_types.d.ts +47 -0
  39. package/dist/event_types.d.ts.map +1 -0
  40. package/dist/event_types.js +63 -0
  41. package/dist/event_types.js.map +1 -0
  42. package/dist/hashchain.d.ts +1 -0
  43. package/dist/hashchain.d.ts.map +1 -1
  44. package/dist/hashchain.js +25 -1
  45. package/dist/hashchain.js.map +1 -1
  46. package/dist/index.d.ts +23 -2
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +24 -2
  49. package/dist/index.js.map +1 -1
  50. package/dist/index_version.d.ts +9 -0
  51. package/dist/index_version.d.ts.map +1 -0
  52. package/dist/index_version.js +11 -0
  53. package/dist/index_version.js.map +1 -0
  54. package/dist/intoto.d.ts +48 -0
  55. package/dist/intoto.d.ts.map +1 -0
  56. package/dist/intoto.js +106 -0
  57. package/dist/intoto.js.map +1 -0
  58. package/dist/obligations.d.ts +41 -0
  59. package/dist/obligations.d.ts.map +1 -0
  60. package/dist/obligations.js +312 -0
  61. package/dist/obligations.js.map +1 -0
  62. package/dist/proof_bundle.d.ts +186 -0
  63. package/dist/proof_bundle.d.ts.map +1 -0
  64. package/dist/proof_bundle.js +299 -0
  65. package/dist/proof_bundle.js.map +1 -0
  66. package/dist/reason_codes.d.ts +38 -0
  67. package/dist/reason_codes.d.ts.map +1 -0
  68. package/dist/reason_codes.js +97 -0
  69. package/dist/reason_codes.js.map +1 -0
  70. package/dist/replay_verifier.d.ts +43 -0
  71. package/dist/replay_verifier.d.ts.map +1 -0
  72. package/dist/replay_verifier.js +98 -0
  73. package/dist/replay_verifier.js.map +1 -0
  74. package/dist/rfc3161.d.ts +52 -0
  75. package/dist/rfc3161.d.ts.map +1 -0
  76. package/dist/rfc3161.js +480 -0
  77. package/dist/rfc3161.js.map +1 -0
  78. package/dist/settlement_verifier.d.ts +34 -0
  79. package/dist/settlement_verifier.d.ts.map +1 -0
  80. package/dist/settlement_verifier.js +139 -0
  81. package/dist/settlement_verifier.js.map +1 -0
  82. package/dist/signing/base.d.ts +101 -0
  83. package/dist/signing/base.d.ts.map +1 -0
  84. package/dist/signing/base.js +144 -0
  85. package/dist/signing/base.js.map +1 -0
  86. package/dist/signing/providers.d.ts +113 -0
  87. package/dist/signing/providers.d.ts.map +1 -0
  88. package/dist/signing/providers.js +230 -0
  89. package/dist/signing/providers.js.map +1 -0
  90. package/dist/signing/signer.d.ts +66 -0
  91. package/dist/signing/signer.d.ts.map +1 -0
  92. package/dist/signing/signer.js +146 -0
  93. package/dist/signing/signer.js.map +1 -0
  94. package/dist/signing/trust_roots.d.ts +71 -0
  95. package/dist/signing/trust_roots.d.ts.map +1 -0
  96. package/dist/signing/trust_roots.js +267 -0
  97. package/dist/signing/trust_roots.js.map +1 -0
  98. package/dist/signing/verifier_ext.d.ts +77 -0
  99. package/dist/signing/verifier_ext.d.ts.map +1 -0
  100. package/dist/signing/verifier_ext.js +340 -0
  101. package/dist/signing/verifier_ext.js.map +1 -0
  102. package/dist/verifier.d.ts +39 -0
  103. package/dist/verifier.d.ts.map +1 -0
  104. package/dist/verifier.js +374 -0
  105. package/dist/verifier.js.map +1 -0
  106. package/package.json +2 -2
@@ -0,0 +1,480 @@
1
+ // SPDX-FileCopyrightText: 2026 The Attestplane Authors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * RFC-3161 TimeStampResp parsing + TimeStampToken signature verification
5
+ * (TypeScript port of `sdk/python/src/attestplane/anchoring/rfc3161.py`).
6
+ *
7
+ * Built on `src/der.ts` (hand-rolled DER reader) + Node's stdlib
8
+ * `crypto.verify` for RSA-PKCS1v15-SHA256. No additional npm
9
+ * dependencies — the TypeScript SDK keeps the same lean dep tree as
10
+ * v0.0.1-alpha while gaining real signature verification.
11
+ *
12
+ * The parser handles the specific structures defined in RFC-3161,
13
+ * RFC-5652 (CMS SignedData), and the X.509 subset needed to extract
14
+ * the RSA public key from a leaf cert's SubjectPublicKeyInfo.
15
+ *
16
+ * Cross-language conformance: TS reproduces Python's
17
+ * parse_timestamp_response semantics byte-for-byte. The
18
+ * anchor_vectors.json fixtures verify in both languages.
19
+ */
20
+ import { createPublicKey, createVerify } from 'node:crypto';
21
+ import { AnchorVerificationError } from './anchoring.js';
22
+ import { DerParseError, getValueBytes, readBitString, readGeneralizedTime, readInteger, readOctetString, readOid, readSequence, readTlv, tlvDer, } from './der.js';
23
+ // Well-known OIDs used in the structures we parse.
24
+ const OID_SIGNED_DATA = '1.2.840.113549.1.7.2';
25
+ const OID_TST_INFO = '1.2.840.113549.1.9.16.1.4';
26
+ function topSequence(buffer) {
27
+ const tlv = readTlv(buffer, 0);
28
+ if (tlv.tag !== 0x30) {
29
+ throw new AnchorVerificationError(`expected SEQUENCE (0x30) at top, got 0x${tlv.tag.toString(16)}`);
30
+ }
31
+ return tlv;
32
+ }
33
+ function tryWrapAsSet(buffer) {
34
+ // Some CMS SignerInfo signedAttrs are encoded with IMPLICIT [0]
35
+ // (tag 0xA0) but the signature input is computed over the SET-tagged
36
+ // form (0x31). Rewrite the first byte to 0x31 to match.
37
+ if (buffer.length === 0)
38
+ return buffer;
39
+ const out = new Uint8Array(buffer);
40
+ if (out[0] === 0xa0 || out[0] === 0xa1) {
41
+ out[0] = 0x31;
42
+ }
43
+ return out;
44
+ }
45
+ /** Parse a DER-encoded TimeStampResp into the substantive fields we verify. */
46
+ export function parseTimestampResponse(responseDer) {
47
+ let response;
48
+ try {
49
+ response = topSequence(responseDer);
50
+ }
51
+ catch (exc) {
52
+ if (exc instanceof DerParseError) {
53
+ throw new AnchorVerificationError(`timestamp response is not valid DER: ${exc.message}`);
54
+ }
55
+ throw exc;
56
+ }
57
+ const responseFields = readSequence(response);
58
+ if (responseFields.length < 1) {
59
+ throw new AnchorVerificationError('timestamp response: missing PKIStatusInfo');
60
+ }
61
+ // PKIStatusInfo ::= SEQUENCE { status INTEGER, statusString OPTIONAL, failInfo OPTIONAL }
62
+ const statusInfo = responseFields[0];
63
+ if (statusInfo.tag !== 0x30) {
64
+ throw new AnchorVerificationError('PKIStatusInfo is not a SEQUENCE');
65
+ }
66
+ const statusItems = readSequence(statusInfo);
67
+ if (statusItems.length === 0) {
68
+ throw new AnchorVerificationError('PKIStatusInfo: missing status');
69
+ }
70
+ const status = Number(readInteger(statusItems[0]));
71
+ // 0 = granted, 1 = grantedWithMods, others = rejection.
72
+ if (status !== 0 && status !== 1) {
73
+ throw new AnchorVerificationError(`TSA refused request: PKIStatus=${status}`);
74
+ }
75
+ if (responseFields.length < 2) {
76
+ throw new AnchorVerificationError('TimeStampResp: missing TimeStampToken');
77
+ }
78
+ // TimeStampToken is a ContentInfo (CMS SignedData).
79
+ const contentInfo = responseFields[1];
80
+ if (contentInfo.tag !== 0x30) {
81
+ throw new AnchorVerificationError('TimeStampToken is not a ContentInfo SEQUENCE');
82
+ }
83
+ const contentInfoFields = readSequence(contentInfo);
84
+ if (contentInfoFields.length < 2) {
85
+ throw new AnchorVerificationError('ContentInfo: missing fields');
86
+ }
87
+ const contentTypeOid = readOid(contentInfoFields[0]);
88
+ if (contentTypeOid !== OID_SIGNED_DATA) {
89
+ throw new AnchorVerificationError(`TimeStampToken content_type is not signed_data: ${contentTypeOid}`);
90
+ }
91
+ const contentExplicit = contentInfoFields[1];
92
+ if (contentExplicit.tag !== 0xa0) {
93
+ throw new AnchorVerificationError('ContentInfo content not in EXPLICIT [0]');
94
+ }
95
+ const signedDataItems = readSequence(readSequence(contentExplicit)[0]);
96
+ // SignedData ::= SEQUENCE { version, digestAlgorithms SET, encapContentInfo,
97
+ // certificates [0] IMPLICIT OPTIONAL, crls [1] IMPLICIT OPTIONAL,
98
+ // signerInfos SET }
99
+ // version is first INTEGER; digestAlgorithms is SET; encapContentInfo is SEQUENCE.
100
+ if (signedDataItems.length < 4) {
101
+ throw new AnchorVerificationError('SignedData: too few fields');
102
+ }
103
+ // signedDataItems[0] = version, [1] = digestAlgorithms SET, [2] = encapContentInfo SEQUENCE.
104
+ const encapContentInfo = signedDataItems[2];
105
+ if (encapContentInfo.tag !== 0x30) {
106
+ throw new AnchorVerificationError('EncapsulatedContentInfo not a SEQUENCE');
107
+ }
108
+ const encapFields = readSequence(encapContentInfo);
109
+ if (encapFields.length < 2) {
110
+ throw new AnchorVerificationError('EncapsulatedContentInfo missing eContent');
111
+ }
112
+ const eContentTypeOid = readOid(encapFields[0]);
113
+ if (eContentTypeOid !== OID_TST_INFO) {
114
+ throw new AnchorVerificationError(`encap content_type is not tst_info: ${eContentTypeOid}`);
115
+ }
116
+ const eContentExplicit = encapFields[1];
117
+ if (eContentExplicit.tag !== 0xa0) {
118
+ throw new AnchorVerificationError('eContent not in EXPLICIT [0]');
119
+ }
120
+ // Inside EXPLICIT [0] is OCTET STRING containing TSTInfo DER bytes.
121
+ const eContentInner = readTlv(eContentExplicit.buffer, eContentExplicit.valueStart);
122
+ const tstInfoDer = readOctetString(eContentInner);
123
+ const tstInfo = topSequence(tstInfoDer);
124
+ const tstFields = readSequence(tstInfo);
125
+ // TSTInfo ::= SEQUENCE { version, policy OID, messageImprint, serialNumber, genTime,
126
+ // accuracy OPTIONAL, ordering BOOLEAN OPTIONAL, nonce OPTIONAL,
127
+ // tsa [0] OPTIONAL, extensions [1] OPTIONAL }
128
+ if (tstFields.length < 5) {
129
+ throw new AnchorVerificationError('TSTInfo: too few fields');
130
+ }
131
+ const policyOid = readOid(tstFields[1]);
132
+ const messageImprintSeq = tstFields[2];
133
+ if (messageImprintSeq.tag !== 0x30) {
134
+ throw new AnchorVerificationError('MessageImprint is not a SEQUENCE');
135
+ }
136
+ const messageImprintFields = readSequence(messageImprintSeq);
137
+ // MessageImprint ::= SEQUENCE { hashAlgorithm AlgorithmIdentifier, hashedMessage OCTET STRING }
138
+ const hashAlgOid = readOid(readSequence(messageImprintFields[0])[0]);
139
+ const hashAlgorithm = hashAlgOid === '2.16.840.1.101.3.4.2.1' ? 'sha256' : hashAlgOid;
140
+ const hashedMessage = readOctetString(messageImprintFields[1]);
141
+ const serialNumber = readInteger(tstFields[3]);
142
+ const genTime = readGeneralizedTime(tstFields[4]);
143
+ // Optional nonce (INTEGER, tag 0x02).
144
+ let nonce = null;
145
+ for (let i = 5; i < tstFields.length; i++) {
146
+ const f = tstFields[i];
147
+ if (f.tag === 0x02) {
148
+ nonce = readInteger(f);
149
+ break;
150
+ }
151
+ }
152
+ // Extract the leaf cert from the optional certificates [0] IMPLICIT field.
153
+ // It's tag 0xA0 (context [0] constructed) right after encapContentInfo.
154
+ let certsField = null;
155
+ for (let i = 3; i < signedDataItems.length; i++) {
156
+ const f = signedDataItems[i];
157
+ if (f.tag === 0xa0) {
158
+ certsField = f;
159
+ break;
160
+ }
161
+ }
162
+ if (certsField === null) {
163
+ throw new AnchorVerificationError('SignedData has no certificates');
164
+ }
165
+ const certs = readSequence(certsField);
166
+ if (certs.length === 0) {
167
+ throw new AnchorVerificationError('certificates set is empty');
168
+ }
169
+ const leafCertDer = tlvDer(certs[0]);
170
+ // Find signerInfos SET (last SET in signedDataItems).
171
+ let signerInfosField = null;
172
+ for (let i = signedDataItems.length - 1; i >= 0; i--) {
173
+ const f = signedDataItems[i];
174
+ if (f.tag === 0x31) {
175
+ signerInfosField = f;
176
+ break;
177
+ }
178
+ }
179
+ if (signerInfosField === null) {
180
+ throw new AnchorVerificationError('SignerInfos SET not found');
181
+ }
182
+ const signerInfos = readSequence(signerInfosField);
183
+ if (signerInfos.length !== 1) {
184
+ throw new AnchorVerificationError(`expected exactly one SignerInfo, got ${signerInfos.length}`);
185
+ }
186
+ const signerInfo = signerInfos[0];
187
+ // SignerInfo ::= SEQUENCE { version, sid, digestAlgorithm, signedAttrs [0] IMPLICIT OPTIONAL,
188
+ // signatureAlgorithm, signature, unsignedAttrs [1] OPTIONAL }
189
+ const siFields = readSequence(signerInfo);
190
+ // Find signedAttrs (tag 0xA0).
191
+ let signedAttrs = null;
192
+ let digestAlgo = null;
193
+ let signatureAlgo = null;
194
+ let signatureField = null;
195
+ let sawSid = false;
196
+ for (let i = 0; i < siFields.length; i++) {
197
+ const f = siFields[i];
198
+ if (i === 0)
199
+ continue; // version
200
+ if (!sawSid) {
201
+ sawSid = true;
202
+ continue; // sid
203
+ }
204
+ if (digestAlgo === null && f.tag === 0x30) {
205
+ digestAlgo = f;
206
+ continue;
207
+ }
208
+ if (f.tag === 0xa0 && signedAttrs === null) {
209
+ signedAttrs = f;
210
+ continue;
211
+ }
212
+ if (signatureAlgo === null && f.tag === 0x30) {
213
+ signatureAlgo = f;
214
+ continue;
215
+ }
216
+ if (signatureField === null && f.tag === 0x04) {
217
+ signatureField = f;
218
+ break;
219
+ }
220
+ }
221
+ if (signedAttrs === null ||
222
+ signatureAlgo === null ||
223
+ signatureField === null ||
224
+ digestAlgo === null) {
225
+ throw new AnchorVerificationError('SignerInfo missing required fields');
226
+ }
227
+ const signedAttrsDer = tryWrapAsSet(tlvDer(signedAttrs));
228
+ const signature = readOctetString(signatureField);
229
+ const digestAlgorithmOid = readOid(readSequence(digestAlgo)[0]);
230
+ const signatureAlgorithmOid = readOid(readSequence(signatureAlgo)[0]);
231
+ return {
232
+ policyOid,
233
+ hashAlgorithm,
234
+ messageImprint: hashedMessage,
235
+ genTime,
236
+ serialNumber,
237
+ nonce,
238
+ leafCertDer,
239
+ signedAttrsDer,
240
+ signature,
241
+ digestAlgorithmOid,
242
+ signatureAlgorithmOid,
243
+ };
244
+ }
245
+ function readUtcOrGeneralizedTime(tlv) {
246
+ // UTCTime (0x17) format: YYMMDDhhmmssZ
247
+ // GeneralizedTime (0x18) format: YYYYMMDDhhmmss[.fff]Z
248
+ if (tlv.tag === 0x18) {
249
+ return readGeneralizedTime(tlv);
250
+ }
251
+ if (tlv.tag !== 0x17) {
252
+ throw new AnchorVerificationError(`expected UTCTime/GeneralizedTime, got 0x${tlv.tag.toString(16)}`);
253
+ }
254
+ const text = new TextDecoder('ascii').decode(getValueBytes(tlv));
255
+ if (!text.endsWith('Z')) {
256
+ throw new AnchorVerificationError(`UTCTime not in UTC Z form: ${text}`);
257
+ }
258
+ const stripped = text.slice(0, -1);
259
+ const m = /^(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/.exec(stripped);
260
+ if (!m) {
261
+ throw new AnchorVerificationError(`UTCTime not parseable: ${text}`);
262
+ }
263
+ const yy = Number(m[1]);
264
+ const year = yy < 50 ? 2000 + yy : 1900 + yy;
265
+ return new Date(`${year}-${m[2]}-${m[3]}T${m[4]}:${m[5]}:${m[6]}Z`);
266
+ }
267
+ function parseCertificate(der) {
268
+ const cert = topSequence(der);
269
+ const certFields = readSequence(cert);
270
+ if (certFields.length < 3) {
271
+ throw new AnchorVerificationError('Certificate: too few fields');
272
+ }
273
+ const tbs = certFields[0];
274
+ const sigAlg = certFields[1];
275
+ const sigField = certFields[2];
276
+ const tbsFields = readSequence(tbs);
277
+ // TBSCertificate ::= SEQUENCE { [0] EXPLICIT Version OPTIONAL, serialNumber INTEGER,
278
+ // signature AlgorithmIdentifier, issuer Name, validity Validity,
279
+ // subject Name, subjectPublicKeyInfo SubjectPublicKeyInfo,
280
+ // ... extensions [3] EXPLICIT OPTIONAL }
281
+ let cursor = 0;
282
+ // Optional version [0] EXPLICIT.
283
+ if (tbsFields[cursor].tag === 0xa0) {
284
+ cursor += 1;
285
+ }
286
+ cursor += 1; // serialNumber
287
+ cursor += 1; // signature AlgorithmIdentifier
288
+ const issuerDer = tlvDer(tbsFields[cursor]);
289
+ cursor += 1;
290
+ const validity = tbsFields[cursor];
291
+ cursor += 1;
292
+ const subjectDer = tlvDer(tbsFields[cursor]);
293
+ cursor += 1;
294
+ const spki = tbsFields[cursor];
295
+ cursor += 1;
296
+ const validityFields = readSequence(validity);
297
+ const notBefore = readUtcOrGeneralizedTime(validityFields[0]);
298
+ const notAfter = readUtcOrGeneralizedTime(validityFields[1]);
299
+ // Convert SPKI to a Node KeyObject.
300
+ let publicKey;
301
+ try {
302
+ publicKey = createPublicKey({ key: Buffer.from(tlvDer(spki)), format: 'der', type: 'spki' });
303
+ }
304
+ catch (exc) {
305
+ throw new AnchorVerificationError(`failed to parse SubjectPublicKeyInfo: ${exc instanceof Error ? exc.message : String(exc)}`);
306
+ }
307
+ // BasicConstraints CA flag: walk extensions if present.
308
+ let isCa = false;
309
+ while (cursor < tbsFields.length) {
310
+ const f = tbsFields[cursor];
311
+ cursor += 1;
312
+ if (f.tag !== 0xa3)
313
+ continue; // extensions are [3] EXPLICIT
314
+ const extsSeq = readSequence(f)[0];
315
+ const exts = readSequence(extsSeq);
316
+ for (const ext of exts) {
317
+ // Each ext: SEQUENCE { extnID OID, critical BOOLEAN OPT, extnValue OCTET STRING }
318
+ const extFields = readSequence(ext);
319
+ const oid = readOid(extFields[0]);
320
+ if (oid !== '2.5.29.19')
321
+ continue; // basicConstraints
322
+ // extnValue is the last OCTET STRING.
323
+ const valueBytes = readOctetString(extFields[extFields.length - 1]);
324
+ const bcSeq = readTlv(valueBytes, 0);
325
+ const bcFields = readSequence(bcSeq);
326
+ if (bcFields.length > 0) {
327
+ const cTlv = bcFields[0];
328
+ if (cTlv.tag === 0x01) {
329
+ // BOOLEAN: cA. Non-zero value = true.
330
+ isCa = cTlv.buffer[cTlv.valueStart] !== 0;
331
+ }
332
+ }
333
+ }
334
+ }
335
+ // signature BIT STRING.
336
+ const { unusedBits: _unused, bytes: sigBytes } = readBitString(sigField);
337
+ const signatureAlgorithmOid = readOid(readSequence(sigAlg)[0]);
338
+ return {
339
+ der,
340
+ subjectDer,
341
+ issuerDer,
342
+ notBefore,
343
+ notAfter,
344
+ publicKey,
345
+ tbsBytes: tlvDer(tbs),
346
+ signatureAlgorithmOid,
347
+ signature: sigBytes,
348
+ isCa,
349
+ };
350
+ }
351
+ function bytesEqual(a, b) {
352
+ if (a.length !== b.length)
353
+ return false;
354
+ for (let i = 0; i < a.length; i++) {
355
+ if (a[i] !== b[i])
356
+ return false;
357
+ }
358
+ return true;
359
+ }
360
+ function verifyRsaSha256(publicKey, data, signature) {
361
+ const v = createVerify('RSA-SHA256');
362
+ v.update(Buffer.from(data));
363
+ v.end();
364
+ return v.verify(publicKey, Buffer.from(signature));
365
+ }
366
+ /**
367
+ * Verify a parsed TimeStampToken against the expected message digest +
368
+ * trust roots + intermediates.
369
+ *
370
+ * Mirrors the Python `verify_timestamp_token` API including multi-hop
371
+ * intermediate chain walking, time-validity checks at every cert, and
372
+ * BasicConstraints.cA enforcement on each intermediate.
373
+ *
374
+ * Throws `AnchorVerificationError` on any failure.
375
+ */
376
+ export function verifyTimestampToken(parsed, options) {
377
+ const { expectedDigest, trustRootsDer, intermediatesDer = [], verificationTime, maxChainDepth = 8, } = options;
378
+ if (expectedDigest.length !== 32) {
379
+ throw new AnchorVerificationError(`expectedDigest must be 32 bytes, got ${expectedDigest.length}`);
380
+ }
381
+ if (parsed.hashAlgorithm !== 'sha256') {
382
+ throw new AnchorVerificationError(`unexpected message-imprint hash algorithm: ${parsed.hashAlgorithm}`);
383
+ }
384
+ if (!bytesEqual(parsed.messageImprint, expectedDigest)) {
385
+ throw new AnchorVerificationError('message_imprint does not match expected digest');
386
+ }
387
+ let leaf;
388
+ try {
389
+ leaf = parseCertificate(parsed.leafCertDer);
390
+ }
391
+ catch (exc) {
392
+ throw new AnchorVerificationError(`leaf cert is not valid DER: ${exc instanceof Error ? exc.message : String(exc)}`);
393
+ }
394
+ // Verify the TSA signature over signedAttrs using the leaf cert's
395
+ // public key.
396
+ if (!verifyRsaSha256(leaf.publicKey, parsed.signedAttrsDer, parsed.signature)) {
397
+ throw new AnchorVerificationError('TSA signature does not verify against leaf cert');
398
+ }
399
+ // Time validity for the leaf.
400
+ const when = verificationTime ?? new Date();
401
+ if (when < leaf.notBefore) {
402
+ throw new AnchorVerificationError(`verification_time ${when.toISOString()} precedes leaf cert not_before ${leaf.notBefore.toISOString()}`);
403
+ }
404
+ if (when > leaf.notAfter) {
405
+ throw new AnchorVerificationError(`verification_time ${when.toISOString()} exceeds leaf cert not_after ${leaf.notAfter.toISOString()}`);
406
+ }
407
+ // Chain walk.
408
+ const intermediates = [];
409
+ for (const der of intermediatesDer) {
410
+ try {
411
+ intermediates.push(parseCertificate(der));
412
+ }
413
+ catch {
414
+ // Skip malformed intermediates.
415
+ }
416
+ }
417
+ const roots = [];
418
+ for (const der of trustRootsDer) {
419
+ try {
420
+ roots.push(parseCertificate(der));
421
+ }
422
+ catch {
423
+ // Skip malformed roots.
424
+ }
425
+ }
426
+ if (roots.length === 0) {
427
+ throw new AnchorVerificationError('no parseable trust roots provided');
428
+ }
429
+ let current = leaf;
430
+ const visited = new Set();
431
+ visited.add(`${bytesToHexString(current.subjectDer)}:${bytesToHexString(current.tbsBytes.slice(0, 4))}`);
432
+ for (let hop = 0; hop < maxChainDepth; hop++) {
433
+ const matchedRoot = findIssuer(current, roots);
434
+ if (matchedRoot !== null) {
435
+ verifyLink(current, matchedRoot, when);
436
+ return;
437
+ }
438
+ const matchedIntermediate = findIssuer(current, intermediates);
439
+ if (matchedIntermediate === null) {
440
+ throw new AnchorVerificationError(`at hop ${hop}: cert issuer not in trust roots or intermediates`);
441
+ }
442
+ if (!matchedIntermediate.isCa) {
443
+ throw new AnchorVerificationError(`at hop ${hop}: candidate issuer is not a CA (missing BasicConstraints.cA=True)`);
444
+ }
445
+ verifyLink(current, matchedIntermediate, when);
446
+ const key = bytesToHexString(matchedIntermediate.subjectDer);
447
+ if (visited.has(key)) {
448
+ throw new AnchorVerificationError(`chain cycle detected at hop ${hop}`);
449
+ }
450
+ visited.add(key);
451
+ current = matchedIntermediate;
452
+ }
453
+ throw new AnchorVerificationError(`chain depth exceeded maxChainDepth=${maxChainDepth} without reaching a configured trust root`);
454
+ }
455
+ function findIssuer(child, pool) {
456
+ for (const cand of pool) {
457
+ if (bytesEqual(cand.subjectDer, child.issuerDer))
458
+ return cand;
459
+ }
460
+ return null;
461
+ }
462
+ function verifyLink(child, issuer, when) {
463
+ if (when < issuer.notBefore) {
464
+ throw new AnchorVerificationError(`verification_time precedes issuer cert not_before ${issuer.notBefore.toISOString()}`);
465
+ }
466
+ if (when > issuer.notAfter) {
467
+ throw new AnchorVerificationError(`verification_time exceeds issuer cert not_after ${issuer.notAfter.toISOString()}`);
468
+ }
469
+ if (!verifyRsaSha256(issuer.publicKey, child.tbsBytes, child.signature)) {
470
+ throw new AnchorVerificationError('cert signature does not verify against issuer');
471
+ }
472
+ }
473
+ function bytesToHexString(b) {
474
+ let out = '';
475
+ for (let i = 0; i < b.length; i++) {
476
+ out += b[i].toString(16).padStart(2, '0');
477
+ }
478
+ return out;
479
+ }
480
+ //# sourceMappingURL=rfc3161.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rfc3161.js","sourceRoot":"","sources":["../src/rfc3161.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Settlement-precondition verifier predicate — read-only walker, NEVER settles.
3
+ *
4
+ * ADR-0009 § B.3 + P2.3. Walks the chain for an ordered pair of
5
+ * observations: lease consumed → settlement requested (same lease &
6
+ * settlement IDs). Returns yes/no/reason. NEVER executes settlement.
7
+ *
8
+ * **Hard constraint** (per ADR-0009 § B.3 + invariant 7 + REDLINE C.3
9
+ * + C.8): no settlement execution, no budget allocation, no state
10
+ * mutation. Pure function.
11
+ */
12
+ export interface SettlementPreconditionClaim {
13
+ readonly claim_kind: 'settlement_precondition' | string;
14
+ readonly lease_id_hash: string;
15
+ readonly settlement_run_id: string;
16
+ readonly expected_settlement_amount_hash?: string;
17
+ readonly claim_observed_at?: string;
18
+ }
19
+ export interface SettlementVerificationResult {
20
+ readonly ok: boolean;
21
+ readonly reason: string | null;
22
+ readonly lease_consumed_seq: number | null;
23
+ readonly settlement_event_seq: number | null;
24
+ }
25
+ /** Minimal chain-event shape this verifier needs. */
26
+ export interface ChainEventForSettlement {
27
+ readonly seq: number;
28
+ readonly event_type: string;
29
+ readonly payload: Record<string, unknown>;
30
+ }
31
+ export declare function checkSettlementPrecondition(chainEvents: readonly ChainEventForSettlement[], claim: SettlementPreconditionClaim, options?: {
32
+ readonly verification_time?: Date;
33
+ }): SettlementVerificationResult;
34
+ //# sourceMappingURL=settlement_verifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settlement_verifier.d.ts","sourceRoot":"","sources":["../src/settlement_verifier.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,UAAU,EAAE,yBAAyB,GAAG,MAAM,CAAC;IACxD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,+BAA+B,CAAC,EAAE,MAAM,CAAC;IAClD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CACrC;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3C,QAAQ,CAAC,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9C;AAED,qDAAqD;AACrD,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC3C;AAID,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,SAAS,uBAAuB,EAAE,EAC/C,KAAK,EAAE,2BAA2B,EAClC,OAAO,GAAE;IAAE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,IAAI,CAAA;CAAO,GAClD,4BAA4B,CAkI9B"}