@int-loop/core 0.1.0 → 0.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/dist/anchor.d.ts +70 -0
- package/dist/anchor.js +201 -0
- package/dist/comprehension.d.ts +12 -0
- package/dist/comprehension.js +81 -0
- package/dist/der.d.ts +53 -0
- package/dist/der.js +246 -0
- package/dist/evidence-pack.d.ts +11 -2
- package/dist/evidence-pack.js +24 -2
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/schema/ledger.d.ts +3 -1
- package/dist/schema/ledger.js +2 -0
- package/dist/schema/policy.d.ts +3 -0
- package/dist/schema/policy.js +4 -0
- package/dist/schema/request.d.ts +1 -0
- package/dist/schema/request.js +2 -0
- package/dist/tsa-roots.d.ts +9 -0
- package/dist/tsa-roots.js +150 -0
- package/dist/tsp.d.ts +37 -0
- package/dist/tsp.js +228 -0
- package/dist/x509.d.ts +93 -0
- package/dist/x509.js +329 -0
- package/package.json +1 -1
package/dist/evidence-pack.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { type AnchorReport } from "./anchor.ts";
|
|
2
3
|
import { LedgerEntry } from "./schema/ledger.ts";
|
|
3
4
|
import { type VerificationFailure } from "./verify.ts";
|
|
4
5
|
export declare const EVIDENCE_PACK_FORMAT = "int-loop-evidence-pack";
|
|
@@ -33,7 +34,7 @@ export declare const PackKeys: z.ZodObject<{
|
|
|
33
34
|
export type PackKeys = z.infer<typeof PackKeys>;
|
|
34
35
|
/** The hashes of free text a ledger entry references, which the pack should carry. */
|
|
35
36
|
export declare function referencedTextHashes(entry: LedgerEntry): string[];
|
|
36
|
-
export declare const PACK_README = "# int-loop evidence pack\n\nThis archive is a complete, signed record of decisions made through int-loop for one\ntenant. You can check it without trusting int-loop.\n\nRun:\n\n npx @int-loop/verify pack.zip\n\nor, to confirm the service keys are really int-loop's, download\nhttps://int-loop.com/.well-known/int-loop-keys.json and run:\n\n npx @int-loop/verify pack.zip --keys int-loop-keys.json\n\nThe verifier checks that:\n\n1. Every ledger entry links to the one before it (a SHA-256 hash chain from a zero genesis hash).\n2. Every entry carries a valid Ed25519 signature from an int-loop service key.\n3. Every passkey decision (L2 and above) carries a WebAuthn assertion from a passkey enrolled\n earlier in this ledger, by the person the decision names, over a challenge that commits to\n exactly what was displayed, the option chosen, and any reason, conditions or question typed.\n4. Every text in texts.jsonl matches the hash the ledger records for it.\n\nTexts marked \"erased\" were removed under the tenant's retention policy. Their hashes stay in\nthe ledger, so the chain still verifies.\n\nThe verifier is open source (Apache-2.0). This pack is evidence for your own assessment. It is\nnot legal advice and does not on its own show that any regulation is met.\n";
|
|
37
|
+
export declare const PACK_README = "# int-loop evidence pack\n\nThis archive is a complete, signed record of decisions made through int-loop for one\ntenant. You can check it without trusting int-loop.\n\nRun:\n\n npx @int-loop/verify pack.zip\n\nor, to confirm the service keys are really int-loop's, download\nhttps://int-loop.com/.well-known/int-loop-keys.json and run:\n\n npx @int-loop/verify pack.zip --keys int-loop-keys.json\n\nThe verifier checks that:\n\n1. Every ledger entry links to the one before it (a SHA-256 hash chain from a zero genesis hash).\n2. Every entry carries a valid Ed25519 signature from an int-loop service key.\n3. Every passkey decision (L2 and above) carries a WebAuthn assertion from a passkey enrolled\n earlier in this ledger, by the person the decision names, over a challenge that commits to\n exactly what was displayed, the option chosen, and any reason, conditions or question typed.\n4. Every text in texts.jsonl matches the hash the ledger records for it.\n5. Every anchor (an anchor.created entry) holds RFC 3161 timestamps from independent\n timestamp authorities, over a Merkle root that includes the anchored entry. Each\n timestamp must verify against a trusted timestamp authority root. This shows the\n ledger up to that entry existed, unchanged, no later than the stamped time.\n The verifier trusts a short built-in list of roots; pass --tsa-roots roots.pem to\n use your own.\n\nTexts marked \"erased\" were removed under the tenant's retention policy. Their hashes stay in\nthe ledger, so the chain still verifies.\n\nThe verifier is open source (Apache-2.0). This pack is evidence for your own assessment. It is\nnot legal advice and does not on its own show that any regulation is met.\n";
|
|
37
38
|
export declare function crc32(data: Uint8Array): number;
|
|
38
39
|
export declare function buildZip(files: {
|
|
39
40
|
name: string;
|
|
@@ -49,11 +50,19 @@ export type PackReport = {
|
|
|
49
50
|
texts_checked: number;
|
|
50
51
|
texts_erased: number;
|
|
51
52
|
keys_source: "pack" | "trusted";
|
|
53
|
+
anchors_checked: number;
|
|
54
|
+
/** The newest anchored entry, and the earliest time an independent TSA vouches for it. */
|
|
55
|
+
anchored_through: AnchorReport["anchored_through"];
|
|
56
|
+
tsa_roots_source: "default" | "supplied";
|
|
52
57
|
failures: VerificationFailure[];
|
|
53
58
|
};
|
|
59
|
+
export type PackVerifyOptions = {
|
|
60
|
+
/** Trusted timestamp authority roots, as DER certificates. Default: KNOWN_TSA_ROOTS. */
|
|
61
|
+
tsaRoots?: readonly Uint8Array[];
|
|
62
|
+
};
|
|
54
63
|
/**
|
|
55
64
|
* Verifies an evidence pack. With `trustedKeys` (from int-loop's published key list),
|
|
56
65
|
* the pack's own keys.json must agree with them; without, the report says the keys came
|
|
57
66
|
* only from the pack.
|
|
58
67
|
*/
|
|
59
|
-
export declare function verifyEvidencePack(zip: Uint8Array, trustedKeys?: PackKeys): Promise<PackReport>;
|
|
68
|
+
export declare function verifyEvidencePack(zip: Uint8Array, trustedKeys?: PackKeys, options?: PackVerifyOptions): Promise<PackReport>;
|
package/dist/evidence-pack.js
CHANGED
|
@@ -10,9 +10,11 @@
|
|
|
10
10
|
// The zip is stored, not compressed, with fixed timestamps: the same records always
|
|
11
11
|
// produce the same bytes, and the reader needs no decompressor.
|
|
12
12
|
import { z } from "zod";
|
|
13
|
+
import { verifyAnchors } from "./anchor.js";
|
|
13
14
|
import { bytesEqual, fromBase64Url, sha256Hex, utf8 } from "./hash.js";
|
|
14
15
|
import { Base64Url, Sha256Hex, TenantId, Timestamp } from "./schema/common.js";
|
|
15
16
|
import { LedgerEntry, ServiceKeyId } from "./schema/ledger.js";
|
|
17
|
+
import { knownTsaRootsDer } from "./tsa-roots.js";
|
|
16
18
|
import { verifyLedger } from "./verify.js";
|
|
17
19
|
export const EVIDENCE_PACK_FORMAT = "int-loop-evidence-pack";
|
|
18
20
|
export const PackManifest = z.strictObject({
|
|
@@ -75,6 +77,12 @@ The verifier checks that:
|
|
|
75
77
|
earlier in this ledger, by the person the decision names, over a challenge that commits to
|
|
76
78
|
exactly what was displayed, the option chosen, and any reason, conditions or question typed.
|
|
77
79
|
4. Every text in texts.jsonl matches the hash the ledger records for it.
|
|
80
|
+
5. Every anchor (an anchor.created entry) holds RFC 3161 timestamps from independent
|
|
81
|
+
timestamp authorities, over a Merkle root that includes the anchored entry. Each
|
|
82
|
+
timestamp must verify against a trusted timestamp authority root. This shows the
|
|
83
|
+
ledger up to that entry existed, unchanged, no later than the stamped time.
|
|
84
|
+
The verifier trusts a short built-in list of roots; pass --tsa-roots roots.pem to
|
|
85
|
+
use your own.
|
|
78
86
|
|
|
79
87
|
Texts marked "erased" were removed under the tenant's retention policy. Their hashes stay in
|
|
80
88
|
the ledger, so the chain still verifies.
|
|
@@ -201,7 +209,7 @@ export function readZip(zip) {
|
|
|
201
209
|
* the pack's own keys.json must agree with them; without, the report says the keys came
|
|
202
210
|
* only from the pack.
|
|
203
211
|
*/
|
|
204
|
-
export async function verifyEvidencePack(zip, trustedKeys) {
|
|
212
|
+
export async function verifyEvidencePack(zip, trustedKeys, options = {}) {
|
|
205
213
|
const failures = [];
|
|
206
214
|
const report = (extra) => ({
|
|
207
215
|
ok: false,
|
|
@@ -211,6 +219,9 @@ export async function verifyEvidencePack(zip, trustedKeys) {
|
|
|
211
219
|
texts_checked: 0,
|
|
212
220
|
texts_erased: 0,
|
|
213
221
|
keys_source: trustedKeys ? "trusted" : "pack",
|
|
222
|
+
anchors_checked: 0,
|
|
223
|
+
anchored_through: null,
|
|
224
|
+
tsa_roots_source: options.tsaRoots ? "supplied" : "default",
|
|
214
225
|
failures,
|
|
215
226
|
...extra,
|
|
216
227
|
});
|
|
@@ -329,5 +340,16 @@ export async function verifyEvidencePack(zip, trustedKeys) {
|
|
|
329
340
|
if (!present.has(h))
|
|
330
341
|
fail("texts", `entry ${e.seq} references text ${h}, which is not in the pack`, e.seq);
|
|
331
342
|
}
|
|
332
|
-
|
|
343
|
+
const anchors = await verifyAnchors(parsed, options.tsaRoots ?? knownTsaRootsDer());
|
|
344
|
+
failures.push(...anchors.failures);
|
|
345
|
+
return report({
|
|
346
|
+
ok: failures.length === 0,
|
|
347
|
+
manifest,
|
|
348
|
+
entries_checked: ledger.entries_checked,
|
|
349
|
+
decisions_checked: ledger.decisions_checked,
|
|
350
|
+
texts_checked,
|
|
351
|
+
texts_erased,
|
|
352
|
+
anchors_checked: anchors.anchors_checked,
|
|
353
|
+
anchored_through: anchors.anchored_through,
|
|
354
|
+
});
|
|
333
355
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,11 +2,17 @@ export * from "./jcs.ts";
|
|
|
2
2
|
export * from "./hash.ts";
|
|
3
3
|
export * from "./cbor.ts";
|
|
4
4
|
export * from "./binding.ts";
|
|
5
|
+
export * from "./comprehension.ts";
|
|
5
6
|
export * from "./webauthn.ts";
|
|
6
7
|
export * from "./ledger.ts";
|
|
7
8
|
export * from "./verify.ts";
|
|
8
9
|
export * from "./evidence-pack.ts";
|
|
9
10
|
export * from "./receipt.ts";
|
|
11
|
+
export * from "./der.ts";
|
|
12
|
+
export * from "./x509.ts";
|
|
13
|
+
export * from "./tsp.ts";
|
|
14
|
+
export * from "./tsa-roots.ts";
|
|
15
|
+
export * from "./anchor.ts";
|
|
10
16
|
export * from "./schema/common.ts";
|
|
11
17
|
export * from "./schema/request.ts";
|
|
12
18
|
export * from "./schema/directory.ts";
|
package/dist/index.js
CHANGED
|
@@ -2,11 +2,17 @@ export * from "./jcs.js";
|
|
|
2
2
|
export * from "./hash.js";
|
|
3
3
|
export * from "./cbor.js";
|
|
4
4
|
export * from "./binding.js";
|
|
5
|
+
export * from "./comprehension.js";
|
|
5
6
|
export * from "./webauthn.js";
|
|
6
7
|
export * from "./ledger.js";
|
|
7
8
|
export * from "./verify.js";
|
|
8
9
|
export * from "./evidence-pack.js";
|
|
9
10
|
export * from "./receipt.js";
|
|
11
|
+
export * from "./der.js";
|
|
12
|
+
export * from "./x509.js";
|
|
13
|
+
export * from "./tsp.js";
|
|
14
|
+
export * from "./tsa-roots.js";
|
|
15
|
+
export * from "./anchor.js";
|
|
10
16
|
export * from "./schema/common.js";
|
|
11
17
|
export * from "./schema/request.js";
|
|
12
18
|
export * from "./schema/directory.js";
|
package/dist/schema/ledger.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
export declare const LEDGER_ENTRY_TYPES: readonly ["request.created", "request.routed", "notification.sent", "notification.failed", "request.viewed", "decision.cast", "decision.invalidated", "request.info_requested", "request.resolved", "request.expired", "request.cancelled", "policy.loaded", "directory.changed", "passkey.enrolled", "passkey.revoked", "export.created", "pack.activated", "pack.deactivated", "anchor.created"];
|
|
2
|
+
export declare const LEDGER_ENTRY_TYPES: readonly ["request.created", "request.routed", "notification.sent", "notification.failed", "request.viewed", "decision.cast", "decision.invalidated", "request.info_requested", "request.resolved", "request.expired", "request.cancelled", "receipt.redeemed", "policy.loaded", "directory.changed", "passkey.enrolled", "passkey.revoked", "export.created", "pack.activated", "pack.deactivated", "anchor.created"];
|
|
3
3
|
export declare const LedgerEntryType: z.ZodEnum<{
|
|
4
4
|
"anchor.created": "anchor.created";
|
|
5
5
|
"decision.cast": "decision.cast";
|
|
@@ -13,6 +13,7 @@ export declare const LedgerEntryType: z.ZodEnum<{
|
|
|
13
13
|
"passkey.enrolled": "passkey.enrolled";
|
|
14
14
|
"passkey.revoked": "passkey.revoked";
|
|
15
15
|
"policy.loaded": "policy.loaded";
|
|
16
|
+
"receipt.redeemed": "receipt.redeemed";
|
|
16
17
|
"request.cancelled": "request.cancelled";
|
|
17
18
|
"request.created": "request.created";
|
|
18
19
|
"request.expired": "request.expired";
|
|
@@ -39,6 +40,7 @@ export declare const LedgerEntry: z.ZodObject<{
|
|
|
39
40
|
"passkey.enrolled": "passkey.enrolled";
|
|
40
41
|
"passkey.revoked": "passkey.revoked";
|
|
41
42
|
"policy.loaded": "policy.loaded";
|
|
43
|
+
"receipt.redeemed": "receipt.redeemed";
|
|
42
44
|
"request.cancelled": "request.cancelled";
|
|
43
45
|
"request.created": "request.created";
|
|
44
46
|
"request.expired": "request.expired";
|
package/dist/schema/ledger.js
CHANGED
|
@@ -13,6 +13,8 @@ export const LEDGER_ENTRY_TYPES = [
|
|
|
13
13
|
"request.resolved",
|
|
14
14
|
"request.expired",
|
|
15
15
|
"request.cancelled",
|
|
16
|
+
// The executor used the request's receipt. A receipt is redeemed at most once.
|
|
17
|
+
"receipt.redeemed",
|
|
16
18
|
"policy.loaded",
|
|
17
19
|
"directory.changed",
|
|
18
20
|
"passkey.enrolled",
|
package/dist/schema/policy.d.ts
CHANGED
|
@@ -136,6 +136,7 @@ export declare const Rule: z.ZodObject<{
|
|
|
136
136
|
L4: "L4";
|
|
137
137
|
}>>;
|
|
138
138
|
respond_within: z.ZodOptional<z.ZodString>;
|
|
139
|
+
remind_after: z.ZodOptional<z.ZodString>;
|
|
139
140
|
separation_of_duties: z.ZodOptional<z.ZodBoolean>;
|
|
140
141
|
}, z.core.$strict>;
|
|
141
142
|
export type Rule = z.infer<typeof Rule>;
|
|
@@ -150,6 +151,7 @@ export declare const Policy: z.ZodObject<{
|
|
|
150
151
|
L4: "L4";
|
|
151
152
|
}>>;
|
|
152
153
|
respond_within: z.ZodDefault<z.ZodString>;
|
|
154
|
+
remind_after: z.ZodOptional<z.ZodString>;
|
|
153
155
|
on_timeout: z.ZodDefault<z.ZodLiteral<"expired">>;
|
|
154
156
|
deny_is_veto: z.ZodDefault<z.ZodBoolean>;
|
|
155
157
|
}, z.core.$strict>;
|
|
@@ -206,6 +208,7 @@ export declare const Policy: z.ZodObject<{
|
|
|
206
208
|
L4: "L4";
|
|
207
209
|
}>>;
|
|
208
210
|
respond_within: z.ZodOptional<z.ZodString>;
|
|
211
|
+
remind_after: z.ZodOptional<z.ZodString>;
|
|
209
212
|
separation_of_duties: z.ZodOptional<z.ZodBoolean>;
|
|
210
213
|
}, z.core.$strict>>;
|
|
211
214
|
}, z.core.$strict>;
|
package/dist/schema/policy.js
CHANGED
|
@@ -45,6 +45,8 @@ export const Rule = z.strictObject({
|
|
|
45
45
|
stages: z.array(Stage).min(1),
|
|
46
46
|
assurance: AssuranceLevel.optional(),
|
|
47
47
|
respond_within: Duration.optional(),
|
|
48
|
+
// Remind approvers who have not decided once this long after the request is sent. The shortest applicable wins.
|
|
49
|
+
remind_after: Duration.optional(),
|
|
48
50
|
separation_of_duties: z.boolean().optional(),
|
|
49
51
|
});
|
|
50
52
|
export const Policy = z
|
|
@@ -54,6 +56,8 @@ export const Policy = z
|
|
|
54
56
|
defaults: z.strictObject({
|
|
55
57
|
assurance: AssuranceLevel.default("L2"),
|
|
56
58
|
respond_within: Duration.default("24h"),
|
|
59
|
+
// Optional: with no remind_after anywhere, nobody is reminded.
|
|
60
|
+
remind_after: Duration.optional(),
|
|
57
61
|
// Timeouts resolve to expired, never to approval. There is no other value.
|
|
58
62
|
on_timeout: z.literal("expired").default("expired"),
|
|
59
63
|
deny_is_veto: z.boolean().default(true),
|
package/dist/schema/request.d.ts
CHANGED
|
@@ -247,5 +247,6 @@ export declare const DecisionStatus: z.ZodObject<{
|
|
|
247
247
|
}, z.core.$strict>;
|
|
248
248
|
sig: z.ZodString;
|
|
249
249
|
}, z.core.$strict>>;
|
|
250
|
+
receipt_redeemed_at: z.ZodNullable<z.ZodISODateTime>;
|
|
250
251
|
}, z.core.$strict>;
|
|
251
252
|
export type DecisionStatus = z.infer<typeof DecisionStatus>;
|
package/dist/schema/request.js
CHANGED
|
@@ -97,4 +97,6 @@ export const DecisionStatus = z.strictObject({
|
|
|
97
97
|
evidence_url: z.url(),
|
|
98
98
|
// Signed proof of what was approved, for the system that carries out the action. Null unless approved or chosen.
|
|
99
99
|
receipt: Receipt.nullable(),
|
|
100
|
+
// When the receipt was redeemed, if it has been. A redeemed receipt cannot be used again.
|
|
101
|
+
receipt_redeemed_at: Timestamp.nullable(),
|
|
100
102
|
});
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
// Timestamp authority roots that int-loop and int-loop-verify trust by default. An auditor
|
|
2
|
+
// can replace this list with their own (int-loop-verify --tsa-roots roots.pem).
|
|
3
|
+
//
|
|
4
|
+
// Provenance, checked 2026-11-09 (SHA-256 fingerprints):
|
|
5
|
+
// FreeTSA Root CA a6379e7cecc05faa3cbf076013d745e327bbbaa38c0b9af22469d4701d18aabc
|
|
6
|
+
// from https://freetsa.org/files/cacert.pem, identical to the root FreeTSA sends
|
|
7
|
+
// DigiCert Trusted Root G4 552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988
|
|
8
|
+
// from the macOS system root store
|
|
9
|
+
// Sectigo Public Time Stamping Root R46
|
|
10
|
+
// 4941b001b8a97e961b7817c9d9e960ec4b056bfc915a8c1aabf6ef6b3ac046a5
|
|
11
|
+
// from the macOS system root store
|
|
12
|
+
//
|
|
13
|
+
// tests/core/tsp.test.ts checks each fingerprint, so a change here cannot go unnoticed.
|
|
14
|
+
import { fromPem } from "./der.js";
|
|
15
|
+
export const KNOWN_TSA_ROOTS = [
|
|
16
|
+
{
|
|
17
|
+
id: "freetsa",
|
|
18
|
+
name: "FreeTSA Root CA",
|
|
19
|
+
sha256: "a6379e7cecc05faa3cbf076013d745e327bbbaa38c0b9af22469d4701d18aabc",
|
|
20
|
+
pem: `
|
|
21
|
+
-----BEGIN CERTIFICATE-----
|
|
22
|
+
MIIH/zCCBeegAwIBAgIJAMHphhYNqOmAMA0GCSqGSIb3DQEBDQUAMIGVMREwDwYD
|
|
23
|
+
VQQKEwhGcmVlIFRTQTEQMA4GA1UECxMHUm9vdCBDQTEYMBYGA1UEAxMPd3d3LmZy
|
|
24
|
+
ZWV0c2Eub3JnMSIwIAYJKoZIhvcNAQkBFhNidXNpbGV6YXNAZ21haWwuY29tMRIw
|
|
25
|
+
EAYDVQQHEwlXdWVyemJ1cmcxDzANBgNVBAgTBkJheWVybjELMAkGA1UEBhMCREUw
|
|
26
|
+
HhcNMTYwMzEzMDE1MjEzWhcNNDEwMzA3MDE1MjEzWjCBlTERMA8GA1UEChMIRnJl
|
|
27
|
+
ZSBUU0ExEDAOBgNVBAsTB1Jvb3QgQ0ExGDAWBgNVBAMTD3d3dy5mcmVldHNhLm9y
|
|
28
|
+
ZzEiMCAGCSqGSIb3DQEJARYTYnVzaWxlemFzQGdtYWlsLmNvbTESMBAGA1UEBxMJ
|
|
29
|
+
V3VlcnpidXJnMQ8wDQYDVQQIEwZCYXllcm4xCzAJBgNVBAYTAkRFMIICIjANBgkq
|
|
30
|
+
hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtgKODjAy8REQ2WTNqUudAnjhlCrpE6ql
|
|
31
|
+
mQfNppeTmVvZrH4zutn+NwTaHAGpjSGv4/WRpZ1wZ3BRZ5mPUBZyLgq0YrIfQ5Fx
|
|
32
|
+
0s/MRZPzc1r3lKWrMR9sAQx4mN4z11xFEO529L0dFJjPF9MD8Gpd2feWzGyptlel
|
|
33
|
+
b+PqT+++fOa2oY0+NaMM7l/xcNHPOaMz0/2olk0i22hbKeVhvokPCqhFhzsuhKsm
|
|
34
|
+
q4Of/o+t6dI7sx5h0nPMm4gGSRhfq+z6BTRgCrqQG2FOLoVFgt6iIm/BnNffUr7V
|
|
35
|
+
DYd3zZmIwFOj/H3DKHoGik/xK3E82YA2ZulVOFRW/zj4ApjPa5OFbpIkd0pmzxzd
|
|
36
|
+
EcL479hSA9dFiyVmSxPtY5ze1P+BE9bMU1PScpRzw8MHFXxyKqW13Qv7LWw4sbk3
|
|
37
|
+
SciB7GACbQiVGzgkvXG6y85HOuvWNvC5GLSiyP9GlPB0V68tbxz4JVTRdw/Xn/XT
|
|
38
|
+
FNzRBM3cq8lBOAVt/PAX5+uFcv1S9wFE8YjaBfWCP1jdBil+c4e+0tdywT2oJmYB
|
|
39
|
+
BF/kEt1wmGwMmHunNEuQNzh1FtJY54hbUfiWi38mASE7xMtMhfj/C4SvapiDN837
|
|
40
|
+
gYaPfs8x3KZxbX7C3YAsFnJinlwAUss1fdKar8Q/YVs7H/nU4c4Ixxxz4f67fcVq
|
|
41
|
+
M2ITKentbCMCAwEAAaOCAk4wggJKMAwGA1UdEwQFMAMBAf8wDgYDVR0PAQH/BAQD
|
|
42
|
+
AgHGMB0GA1UdDgQWBBT6VQ2MNGZRQ0z357OnbJWveuaklzCBygYDVR0jBIHCMIG/
|
|
43
|
+
gBT6VQ2MNGZRQ0z357OnbJWveuakl6GBm6SBmDCBlTERMA8GA1UEChMIRnJlZSBU
|
|
44
|
+
U0ExEDAOBgNVBAsTB1Jvb3QgQ0ExGDAWBgNVBAMTD3d3dy5mcmVldHNhLm9yZzEi
|
|
45
|
+
MCAGCSqGSIb3DQEJARYTYnVzaWxlemFzQGdtYWlsLmNvbTESMBAGA1UEBxMJV3Vl
|
|
46
|
+
cnpidXJnMQ8wDQYDVQQIEwZCYXllcm4xCzAJBgNVBAYTAkRFggkAwemGFg2o6YAw
|
|
47
|
+
MwYDVR0fBCwwKjAooCagJIYiaHR0cDovL3d3dy5mcmVldHNhLm9yZy9yb290X2Nh
|
|
48
|
+
LmNybDCBzwYDVR0gBIHHMIHEMIHBBgorBgEEAYHyJAEBMIGyMDMGCCsGAQUFBwIB
|
|
49
|
+
FidodHRwOi8vd3d3LmZyZWV0c2Eub3JnL2ZyZWV0c2FfY3BzLmh0bWwwMgYIKwYB
|
|
50
|
+
BQUHAgEWJmh0dHA6Ly93d3cuZnJlZXRzYS5vcmcvZnJlZXRzYV9jcHMucGRmMEcG
|
|
51
|
+
CCsGAQUFBwICMDsaOUZyZWVUU0EgdHJ1c3RlZCB0aW1lc3RhbXBpbmcgU29mdHdh
|
|
52
|
+
cmUgYXMgYSBTZXJ2aWNlIChTYWFTKTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUH
|
|
53
|
+
MAGGG2h0dHA6Ly93d3cuZnJlZXRzYS5vcmc6MjU2MDANBgkqhkiG9w0BAQ0FAAOC
|
|
54
|
+
AgEAaK9+v5OFYu9M6ztYC+L69sw1omdyli89lZAfpWMMh9CRmJhM6KBqM/ipwoLt
|
|
55
|
+
nxyxGsbCPhcQjuTvzm+ylN6VwTMmIlVyVSLKYZcdSjt/eCUN+41K7sD7GVmxZBAF
|
|
56
|
+
ILnBDmTGJmLkrU0KuuIpj8lI/E6Z6NnmuP2+RAQSHsfBQi6sssnXMo4HOW5gtPO7
|
|
57
|
+
gDrUpVXID++1P4XndkoKn7Svw5n0zS9fv1hxBcYIHPPQUze2u30bAQt0n0iIyRLz
|
|
58
|
+
aWuhtpAtd7ffwEbASgzB7E+NGF4tpV37e8KiA2xiGSRqT5ndu28fgpOY87gD3ArZ
|
|
59
|
+
DctZvvTCfHdAS5kEO3gnGGeZEVLDmfEsv8TGJa3AljVa5E40IQDsUXpQLi8G+UC4
|
|
60
|
+
1DWZu8EVT4rnYaCw1VX7ShOR1PNCCvjb8S8tfdudd9zhU3gEB0rxdeTy1tVbNLXW
|
|
61
|
+
99y90xcwr1ZIDUwM/xQ/noO8FRhm0LoPC73Ef+J4ZBdrvWwauF3zJe33d4ibxEcb
|
|
62
|
+
8/pz5WzFkeixYM2nsHhqHsBKw7JPouKNXRnl5IAE1eFmqDyC7G/VT7OF669xM6hb
|
|
63
|
+
Ut5G21JE4cNK6NNucS+fzg1JPX0+3VhsYZjj7D5uljRvQXrJ8iHgr/M6j2oLHvTA
|
|
64
|
+
I2MLdq2qjZFDOCXsxBxJpbmLGBx9ow6ZerlUxzws2AWv2pk=
|
|
65
|
+
-----END CERTIFICATE-----
|
|
66
|
+
`,
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
id: "digicert-g4",
|
|
70
|
+
name: "DigiCert Trusted Root G4",
|
|
71
|
+
sha256: "552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988",
|
|
72
|
+
pem: `
|
|
73
|
+
-----BEGIN CERTIFICATE-----
|
|
74
|
+
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
|
|
104
|
+
-----END CERTIFICATE-----
|
|
105
|
+
`,
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: "sectigo-r46",
|
|
109
|
+
name: "Sectigo Public Time Stamping Root R46",
|
|
110
|
+
sha256: "4941b001b8a97e961b7817c9d9e960ec4b056bfc915a8c1aabf6ef6b3ac046a5",
|
|
111
|
+
pem: `
|
|
112
|
+
-----BEGIN CERTIFICATE-----
|
|
113
|
+
MIIFejCCA2KgAwIBAgIQeD0FbPqDLn5p+FYidp8CuTANBgkqhkiG9w0BAQwFADBX
|
|
114
|
+
MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS4wLAYDVQQD
|
|
115
|
+
EyVTZWN0aWdvIFB1YmxpYyBUaW1lIFN0YW1waW5nIFJvb3QgUjQ2MB4XDTIxMDMy
|
|
116
|
+
MjAwMDAwMFoXDTQ2MDMyMTIzNTk1OVowVzELMAkGA1UEBhMCR0IxGDAWBgNVBAoT
|
|
117
|
+
D1NlY3RpZ28gTGltaXRlZDEuMCwGA1UEAxMlU2VjdGlnbyBQdWJsaWMgVGltZSBT
|
|
118
|
+
dGFtcGluZyBSb290IFI0NjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
|
|
119
|
+
AIid2LlFZ50d3ei5JoGaVFTAfEkFm8xaFQ/ZlBBEtEFAgXcUmanU5HYsyAhTXiDQ
|
|
120
|
+
kiUvpVdYqZ1uYoZEMgtHES1l1Cc6HaqZzEbOOp6YiTx63ywTon434aXVydmhx7Dx
|
|
121
|
+
4IBrAou7hNGsKioIBPy5GMN7KmgYmuu4f92sKKjbxqohUSfjk1mJlAjthgF7Hjx4
|
|
122
|
+
vvyVDQGsd5KarLW5d73E3ThobSkob2SL48LpUR/O627pDchxll+bTSv1gASn/hp6
|
|
123
|
+
IuHJorEu6EopoB1CNFp/+HpTXeNARXUmdRMKbnXWflq+/g36NJXB35ZvxQw6zid6
|
|
124
|
+
1qmrlD/IbKJA6COw/8lFSPQwBP1ityZdwuCysCKZ9ZjczMqbUcLFyq6KdOpuzVDR
|
|
125
|
+
3ZUwxDKL1wCAxgL2Mpz7eZbrb/JWXiOcNzDpQsmwGQ6Stw8tTCqPumhLRPb7YkzM
|
|
126
|
+
8/6NnWH3T9ClmcGSF22LEyJYNWCHrQqYubNeKolzqUbCqhSqmr/UdUeb49zYHr7A
|
|
127
|
+
LL8bAJyPDmubNqMtuaobKASBqP84uhqcRY/pjnYd+V5/dcu9ieERjiRKKsxCG1t6
|
|
128
|
+
tG9oj7liwPddXEcYGOUiWLm742st50jGwTzxbMpepmOP1mLnJskvZaN5e45NuzAH
|
|
129
|
+
teORlsSuDt5t4BBRCJL+5EZnnw0ezntk9R8QJyAkL6/bAgMBAAGjQjBAMB0GA1Ud
|
|
130
|
+
DgQWBBT2d2rdP/0BE/8WoWyCAi/QCj0UJTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T
|
|
131
|
+
AQH/BAUwAwEB/zANBgkqhkiG9w0BAQwFAAOCAgEACv68sZqZvmHk7JoU7AfTEZ7b
|
|
132
|
+
X45u40OrLX/6vzHQAwDg1TB00bWbiwj+7+we60BP8AMsw1h5NCXWxeyvrEVC54Mi
|
|
133
|
+
rwVrcF6SFGjRwRoelRuiaZ5FDO4oWhaePjZx3/jkQ7j653CA5WscYqlneLXBEZiY
|
|
134
|
+
o6rRNqnsZHZTQ606mlkNpsy3TFMADv5whZmilVEZ83OvydfH2DNL3FTkpZG7+lHS
|
|
135
|
+
1DFHMSUB5UtSSeSRg2UWTXwU5oObGjFk/35fC/dlF+nJIXdqsw0TZSS86bi5GRCJ
|
|
136
|
+
VjqjnkpZ0Jut7ucEv4PNOIU8ijkMRj17QPjHMtdy+WxBDDSdas/UFTVB/GF+Fofn
|
|
137
|
+
OD3iZ4tXxFjPU3EWRcMWx8fcGyzlBfcjeoPNbNC7wfyV9Qkzfk2Bd48jGxG7OThY
|
|
138
|
+
Wolc56vmBHqDEfguDwYc9AeWirMVRDi+WYlsktzAEObiFoPqs+LWU5q7+Q1+nEcs
|
|
139
|
+
tNuDIedeBRcHmtjL2hV3luuEWwDSnRhSjhPLPXzqpJ1rG3r4yqm1NjKg5A5QO9Az
|
|
140
|
+
veHqRQldluTSKuu96oPEPusL2oF+4MxkJ+SQMGFWTw/PNCblUN8GXeL5+mR20diP
|
|
141
|
+
5LiJMq8U3IpM/0Q7OFFQ+lXuYFIuDvUprWBPsp5La2WhL2+iLVVXItSl7up5yQqX
|
|
142
|
+
XftzTXTX48FRiJ6PA9o=
|
|
143
|
+
-----END CERTIFICATE-----
|
|
144
|
+
`,
|
|
145
|
+
},
|
|
146
|
+
];
|
|
147
|
+
/** The default roots, as DER. */
|
|
148
|
+
export function knownTsaRootsDer() {
|
|
149
|
+
return KNOWN_TSA_ROOTS.flatMap((r) => fromPem(r.pem));
|
|
150
|
+
}
|
package/dist/tsp.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** A TimeStampReq for a SHA-256 digest, asking for the signing certificate to be included. */
|
|
2
|
+
export declare function buildTimestampRequest(digest: Uint8Array, nonce: Uint8Array): Uint8Array<ArrayBuffer>;
|
|
3
|
+
export type TimestampReply = {
|
|
4
|
+
granted: true;
|
|
5
|
+
token: Uint8Array<ArrayBuffer>;
|
|
6
|
+
} | {
|
|
7
|
+
granted: false;
|
|
8
|
+
reason: string;
|
|
9
|
+
};
|
|
10
|
+
/** Reads a TimeStampResp. A refusal is a result, not an error; malformed bytes throw. */
|
|
11
|
+
export declare function parseTimestampReply(bytes: Uint8Array): TimestampReply;
|
|
12
|
+
export type TimestampExpectation = {
|
|
13
|
+
/** The SHA-256 digest that should have been stamped. */
|
|
14
|
+
digest: Uint8Array;
|
|
15
|
+
/** The nonce sent with the request, when checking a fresh reply. */
|
|
16
|
+
nonce?: Uint8Array;
|
|
17
|
+
/** Trusted TSA roots, as DER certificates. */
|
|
18
|
+
roots: readonly Uint8Array[];
|
|
19
|
+
};
|
|
20
|
+
export type TimestampInfo = {
|
|
21
|
+
/** The stamped time, as the TSA states it. */
|
|
22
|
+
gen_time: string;
|
|
23
|
+
serial: string;
|
|
24
|
+
policy: string;
|
|
25
|
+
/** Signing certificate first, trusted root last. */
|
|
26
|
+
chain: string[];
|
|
27
|
+
/** SHA-256 (hex) of the trusted root the chain ends at: which authority vouches for the time. */
|
|
28
|
+
root_sha256: string;
|
|
29
|
+
};
|
|
30
|
+
export type TimestampResult = ({
|
|
31
|
+
ok: true;
|
|
32
|
+
} & TimestampInfo) | {
|
|
33
|
+
ok: false;
|
|
34
|
+
reason: string;
|
|
35
|
+
};
|
|
36
|
+
/** Verifies a TimeStampToken. Never throws: anything malformed is a failure. */
|
|
37
|
+
export declare function verifyTimestampToken(token: Uint8Array, expect: TimestampExpectation): Promise<TimestampResult>;
|