@freedomofpress/sigstore-browser 0.1.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.
Files changed (193) hide show
  1. package/.github/workflows/conformance.yml +29 -0
  2. package/.github/workflows/publish.yml +45 -0
  3. package/README.md +10 -0
  4. package/dist/asn1/error.d.ts +5 -0
  5. package/dist/asn1/error.d.ts.map +1 -0
  6. package/dist/asn1/error.js +20 -0
  7. package/dist/asn1/error.js.map +1 -0
  8. package/dist/asn1/index.d.ts +2 -0
  9. package/dist/asn1/index.d.ts.map +1 -0
  10. package/dist/asn1/index.js +17 -0
  11. package/dist/asn1/index.js.map +1 -0
  12. package/dist/asn1/length.d.ts +4 -0
  13. package/dist/asn1/length.d.ts.map +1 -0
  14. package/dist/asn1/length.js +59 -0
  15. package/dist/asn1/length.js.map +1 -0
  16. package/dist/asn1/obj.d.ts +15 -0
  17. package/dist/asn1/obj.d.ts.map +1 -0
  18. package/dist/asn1/obj.js +153 -0
  19. package/dist/asn1/obj.js.map +1 -0
  20. package/dist/asn1/parse.d.ts +7 -0
  21. package/dist/asn1/parse.d.ts.map +1 -0
  22. package/dist/asn1/parse.js +118 -0
  23. package/dist/asn1/parse.js.map +1 -0
  24. package/dist/asn1/tag.d.ts +17 -0
  25. package/dist/asn1/tag.d.ts.map +1 -0
  26. package/dist/asn1/tag.js +86 -0
  27. package/dist/asn1/tag.js.map +1 -0
  28. package/dist/bundle.d.ts +87 -0
  29. package/dist/bundle.d.ts.map +1 -0
  30. package/dist/bundle.js +2 -0
  31. package/dist/bundle.js.map +1 -0
  32. package/dist/canonicalize.d.ts +2 -0
  33. package/dist/canonicalize.d.ts.map +1 -0
  34. package/dist/canonicalize.js +64 -0
  35. package/dist/canonicalize.js.map +1 -0
  36. package/dist/cli.d.ts +3 -0
  37. package/dist/cli.d.ts.map +1 -0
  38. package/dist/cli.js +217 -0
  39. package/dist/cli.js.map +1 -0
  40. package/dist/crypto.d.ts +5 -0
  41. package/dist/crypto.d.ts.map +1 -0
  42. package/dist/crypto.js +260 -0
  43. package/dist/crypto.js.map +1 -0
  44. package/dist/dsse.d.ts +2 -0
  45. package/dist/dsse.d.ts.map +1 -0
  46. package/dist/dsse.js +42 -0
  47. package/dist/dsse.js.map +1 -0
  48. package/dist/encoding.d.ts +17 -0
  49. package/dist/encoding.d.ts.map +1 -0
  50. package/dist/encoding.js +112 -0
  51. package/dist/encoding.js.map +1 -0
  52. package/dist/errors.d.ts +39 -0
  53. package/dist/errors.d.ts.map +1 -0
  54. package/dist/errors.js +79 -0
  55. package/dist/errors.js.map +1 -0
  56. package/dist/index.d.ts +8 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +5 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/interfaces.d.ts +104 -0
  61. package/dist/interfaces.d.ts.map +1 -0
  62. package/dist/interfaces.js +26 -0
  63. package/dist/interfaces.js.map +1 -0
  64. package/dist/oid.d.ts +5 -0
  65. package/dist/oid.d.ts.map +1 -0
  66. package/dist/oid.js +25 -0
  67. package/dist/oid.js.map +1 -0
  68. package/dist/pem.d.ts +3 -0
  69. package/dist/pem.d.ts.map +1 -0
  70. package/dist/pem.js +41 -0
  71. package/dist/pem.js.map +1 -0
  72. package/dist/rfc3161/error.d.ts +3 -0
  73. package/dist/rfc3161/error.d.ts.map +1 -0
  74. package/dist/rfc3161/error.js +18 -0
  75. package/dist/rfc3161/error.js.map +1 -0
  76. package/dist/rfc3161/index.d.ts +2 -0
  77. package/dist/rfc3161/index.d.ts.map +1 -0
  78. package/dist/rfc3161/index.js +17 -0
  79. package/dist/rfc3161/index.js.map +1 -0
  80. package/dist/rfc3161/timestamp.d.ts +36 -0
  81. package/dist/rfc3161/timestamp.d.ts.map +1 -0
  82. package/dist/rfc3161/timestamp.js +203 -0
  83. package/dist/rfc3161/timestamp.js.map +1 -0
  84. package/dist/rfc3161/tstinfo.d.ts +13 -0
  85. package/dist/rfc3161/tstinfo.d.ts.map +1 -0
  86. package/dist/rfc3161/tstinfo.js +47 -0
  87. package/dist/rfc3161/tstinfo.js.map +1 -0
  88. package/dist/sigstore.d.ts +33 -0
  89. package/dist/sigstore.d.ts.map +1 -0
  90. package/dist/sigstore.js +531 -0
  91. package/dist/sigstore.js.map +1 -0
  92. package/dist/stream.d.ts +22 -0
  93. package/dist/stream.d.ts.map +1 -0
  94. package/dist/stream.js +114 -0
  95. package/dist/stream.js.map +1 -0
  96. package/dist/timestamp/tsa.d.ts +24 -0
  97. package/dist/timestamp/tsa.d.ts.map +1 -0
  98. package/dist/timestamp/tsa.js +150 -0
  99. package/dist/timestamp/tsa.js.map +1 -0
  100. package/dist/tlog/body.d.ts +8 -0
  101. package/dist/tlog/body.d.ts.map +1 -0
  102. package/dist/tlog/body.js +45 -0
  103. package/dist/tlog/body.js.map +1 -0
  104. package/dist/tlog/checkpoint.d.ts +23 -0
  105. package/dist/tlog/checkpoint.d.ts.map +1 -0
  106. package/dist/tlog/checkpoint.js +187 -0
  107. package/dist/tlog/checkpoint.js.map +1 -0
  108. package/dist/tlog/dsse.d.ts +4 -0
  109. package/dist/tlog/dsse.d.ts.map +1 -0
  110. package/dist/tlog/dsse.js +85 -0
  111. package/dist/tlog/dsse.js.map +1 -0
  112. package/dist/tlog/hashedrekord.d.ts +4 -0
  113. package/dist/tlog/hashedrekord.d.ts.map +1 -0
  114. package/dist/tlog/hashedrekord.js +63 -0
  115. package/dist/tlog/hashedrekord.js.map +1 -0
  116. package/dist/tlog/intoto.d.ts +4 -0
  117. package/dist/tlog/intoto.d.ts.map +1 -0
  118. package/dist/tlog/intoto.js +50 -0
  119. package/dist/tlog/intoto.js.map +1 -0
  120. package/dist/tlog/merkle.d.ts +3 -0
  121. package/dist/tlog/merkle.d.ts.map +1 -0
  122. package/dist/tlog/merkle.js +112 -0
  123. package/dist/tlog/merkle.js.map +1 -0
  124. package/dist/trust/tuf-root.json +1 -0
  125. package/dist/trust/tuf.d.ts +95 -0
  126. package/dist/trust/tuf.d.ts.map +1 -0
  127. package/dist/trust/tuf.js +150 -0
  128. package/dist/trust/tuf.js.map +1 -0
  129. package/dist/x509/cert.d.ts +52 -0
  130. package/dist/x509/cert.d.ts.map +1 -0
  131. package/dist/x509/cert.js +256 -0
  132. package/dist/x509/cert.js.map +1 -0
  133. package/dist/x509/chain.d.ts +20 -0
  134. package/dist/x509/chain.d.ts.map +1 -0
  135. package/dist/x509/chain.js +141 -0
  136. package/dist/x509/chain.js.map +1 -0
  137. package/dist/x509/ext.d.ts +48 -0
  138. package/dist/x509/ext.d.ts.map +1 -0
  139. package/dist/x509/ext.js +164 -0
  140. package/dist/x509/ext.js.map +1 -0
  141. package/dist/x509/index.d.ts +4 -0
  142. package/dist/x509/index.d.ts.map +1 -0
  143. package/dist/x509/index.js +19 -0
  144. package/dist/x509/index.js.map +1 -0
  145. package/dist/x509/sct.d.ts +25 -0
  146. package/dist/x509/sct.d.ts.map +1 -0
  147. package/dist/x509/sct.js +123 -0
  148. package/dist/x509/sct.js.map +1 -0
  149. package/eslint.config.mjs +31 -0
  150. package/package.json +39 -0
  151. package/src/asn1/error.ts +18 -0
  152. package/src/asn1/index.ts +16 -0
  153. package/src/asn1/length.ts +71 -0
  154. package/src/asn1/obj.ts +184 -0
  155. package/src/asn1/parse.ts +146 -0
  156. package/src/asn1/tag.ts +105 -0
  157. package/src/bundle.ts +99 -0
  158. package/src/canonicalize.ts +61 -0
  159. package/src/cli.ts +285 -0
  160. package/src/crypto.ts +310 -0
  161. package/src/dsse.ts +49 -0
  162. package/src/encoding.ts +141 -0
  163. package/src/errors.ts +82 -0
  164. package/src/index.browser.test.ts +219 -0
  165. package/src/index.ts +14 -0
  166. package/src/interfaces.ts +118 -0
  167. package/src/oid.ts +28 -0
  168. package/src/pem.ts +48 -0
  169. package/src/rfc3161/error.ts +16 -0
  170. package/src/rfc3161/index.ts +17 -0
  171. package/src/rfc3161/timestamp.ts +270 -0
  172. package/src/rfc3161/tstinfo.ts +80 -0
  173. package/src/sigstore.ts +728 -0
  174. package/src/stream.ts +141 -0
  175. package/src/timestamp/tsa.ts +205 -0
  176. package/src/tlog/body.ts +65 -0
  177. package/src/tlog/checkpoint.ts +248 -0
  178. package/src/tlog/dsse.ts +147 -0
  179. package/src/tlog/hashedrekord.ts +130 -0
  180. package/src/tlog/intoto.ts +102 -0
  181. package/src/tlog/merkle.ts +152 -0
  182. package/src/trust/README.md +38 -0
  183. package/src/trust/tuf-root.json +1 -0
  184. package/src/trust/tuf.ts +223 -0
  185. package/src/types/tuf-browser.d.ts +13 -0
  186. package/src/x509/cert.ts +319 -0
  187. package/src/x509/chain.ts +212 -0
  188. package/src/x509/ext.ts +212 -0
  189. package/src/x509/index.ts +19 -0
  190. package/src/x509/sct.ts +154 -0
  191. package/tsconfig.json +18 -0
  192. package/vite.config.playwright.ts +26 -0
  193. package/vite.config.ts +18 -0
@@ -0,0 +1,85 @@
1
+ /*
2
+ * DSSE transparency log entry verification
3
+ *
4
+ * Based on sigstore-js:
5
+ * https://github.com/sigstore/sigstore-js/blob/main/packages/verify/src/tlog/dsse.ts
6
+ *
7
+ * Key differences from sigstore-js:
8
+ * - Browser-compatible: uses Uint8Array instead of Buffer for binary data
9
+ * - Direct bundle field comparison instead of SignatureContent abstraction
10
+ * - Uses crypto.subtle.digest for hash computation instead of Node.js crypto
11
+ * - Adds verifyDSSE002Body() - new functionality (reference only supports v0.0.1)
12
+ */
13
+ import { base64ToUint8Array, hexToUint8Array, toArrayBuffer, uint8ArrayEqual } from "../encoding.js";
14
+ import { HashAlgorithms } from "../interfaces.js";
15
+ export async function verifyDSSEBody(entry, bundle) {
16
+ const dsseEntry = entry;
17
+ switch (dsseEntry.apiVersion) {
18
+ case "0.0.1":
19
+ return verifyDSSE001Body(dsseEntry, bundle);
20
+ case "0.0.2":
21
+ return verifyDSSE002Body(dsseEntry, bundle);
22
+ default:
23
+ throw new Error(`Unsupported dsse version: ${dsseEntry.apiVersion}`);
24
+ }
25
+ }
26
+ async function verifyDSSE001Body(entry, bundle) {
27
+ if (!bundle.dsseEnvelope) {
28
+ throw new Error("Bundle missing dsseEnvelope for DSSE entry");
29
+ }
30
+ if (!entry.spec.signatures || entry.spec.signatures.length !== 1) {
31
+ throw new Error("DSSE entry must have exactly one signature");
32
+ }
33
+ const tlogSig = entry.spec.signatures[0].signature;
34
+ const tlogSigBytes = base64ToUint8Array(tlogSig);
35
+ if (bundle.dsseEnvelope.signatures.length === 0) {
36
+ throw new Error("Bundle DSSE envelope missing signatures");
37
+ }
38
+ const bundleSigBytes = base64ToUint8Array(bundle.dsseEnvelope.signatures[0].sig);
39
+ if (!uint8ArrayEqual(tlogSigBytes, bundleSigBytes)) {
40
+ throw new Error("DSSE signature mismatch between TLog entry and bundle");
41
+ }
42
+ const tlogHash = entry.spec.payloadHash?.value || "";
43
+ if (!tlogHash) {
44
+ throw new Error("DSSE entry missing payloadHash");
45
+ }
46
+ const tlogHashBytes = hexToUint8Array(tlogHash);
47
+ const payloadBytes = base64ToUint8Array(bundle.dsseEnvelope.payload);
48
+ const bundleHashBytes = new Uint8Array(await crypto.subtle.digest(HashAlgorithms.SHA256, toArrayBuffer(payloadBytes)));
49
+ if (!uint8ArrayEqual(tlogHashBytes, bundleHashBytes)) {
50
+ throw new Error("DSSE payload hash mismatch between TLog entry and bundle");
51
+ }
52
+ }
53
+ // New functionality for DSSE v0.0.2 (not in sigstore-js reference, which only supports v0.0.1)
54
+ async function verifyDSSE002Body(entry, bundle) {
55
+ if (!bundle.dsseEnvelope) {
56
+ throw new Error("Bundle missing dsseEnvelope for DSSE v0.0.2 entry");
57
+ }
58
+ const spec = entry.spec.dsseV002;
59
+ if (!spec) {
60
+ throw new Error("DSSE v0.0.2 entry missing dsseV002 spec");
61
+ }
62
+ if (!spec.signatures || spec.signatures.length !== 1) {
63
+ throw new Error("DSSE v0.0.2 entry must have exactly one signature");
64
+ }
65
+ const tlogSig = spec.signatures[0].content;
66
+ const tlogSigBytes = base64ToUint8Array(tlogSig);
67
+ if (bundle.dsseEnvelope.signatures.length === 0) {
68
+ throw new Error("Bundle DSSE envelope missing signatures");
69
+ }
70
+ const bundleSigBytes = base64ToUint8Array(bundle.dsseEnvelope.signatures[0].sig);
71
+ if (!uint8ArrayEqual(tlogSigBytes, bundleSigBytes)) {
72
+ throw new Error("DSSE signature mismatch between TLog entry and bundle (v0.0.2)");
73
+ }
74
+ const tlogHash = spec.payloadHash?.digest || "";
75
+ if (!tlogHash) {
76
+ throw new Error("DSSE v0.0.2 entry missing payloadHash");
77
+ }
78
+ const tlogHashBytes = base64ToUint8Array(tlogHash);
79
+ const payloadBytes = base64ToUint8Array(bundle.dsseEnvelope.payload);
80
+ const bundleHashBytes = new Uint8Array(await crypto.subtle.digest(HashAlgorithms.SHA256, toArrayBuffer(payloadBytes)));
81
+ if (!uint8ArrayEqual(tlogHashBytes, bundleHashBytes)) {
82
+ throw new Error("DSSE payload hash mismatch between TLog entry and bundle (v0.0.2)");
83
+ }
84
+ }
85
+ //# sourceMappingURL=dsse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dsse.js","sourceRoot":"","sources":["../../src/tlog/dsse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { SigstoreBundle } from "../bundle.js";
2
+ import type { RekorEntry } from "./body.js";
3
+ export declare function verifyHashedRekordBody(entry: RekorEntry, bundle: SigstoreBundle): Promise<void>;
4
+ //# sourceMappingURL=hashedrekord.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hashedrekord.d.ts","sourceRoot":"","sources":["../../src/tlog/hashedrekord.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAwC5C,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC,CAaf"}
@@ -0,0 +1,63 @@
1
+ /*
2
+ * HashedRekord transparency log entry verification
3
+ *
4
+ * Based on sigstore-js:
5
+ * https://github.com/sigstore/sigstore-js/blob/main/packages/verify/src/tlog/hashedrekord.ts
6
+ *
7
+ * Key differences from sigstore-js:
8
+ * - Browser-compatible: uses Uint8Array instead of Buffer for binary data
9
+ * - Direct bundle field comparison instead of SignatureContent abstraction
10
+ * - Adds verifyHashedRekordV002Body() - new functionality (reference only supports v0.0.1)
11
+ */
12
+ import { base64ToUint8Array, hexToUint8Array, uint8ArrayEqual } from "../encoding.js";
13
+ export async function verifyHashedRekordBody(entry, bundle) {
14
+ const hashedRekordEntry = entry;
15
+ switch (hashedRekordEntry.apiVersion) {
16
+ case "0.0.1":
17
+ return verifyHashedRekordV001Body(hashedRekordEntry, bundle);
18
+ case "0.0.2":
19
+ return verifyHashedRekordV002Body(hashedRekordEntry, bundle);
20
+ default:
21
+ throw new Error(`Unsupported hashedrekord version: ${hashedRekordEntry.apiVersion}`);
22
+ }
23
+ }
24
+ function verifyHashedRekordV001Body(entry, bundle) {
25
+ const spec = entry.spec;
26
+ if (!bundle.messageSignature) {
27
+ throw new Error("Bundle missing messageSignature for hashedrekord entry");
28
+ }
29
+ const tlogSig = spec.signature.content || "";
30
+ const tlogSigBytes = base64ToUint8Array(tlogSig);
31
+ const bundleSigBytes = base64ToUint8Array(bundle.messageSignature.signature);
32
+ if (!uint8ArrayEqual(tlogSigBytes, bundleSigBytes)) {
33
+ throw new Error("Signature mismatch between TLog entry and bundle");
34
+ }
35
+ const tlogDigest = spec.data.hash?.value || "";
36
+ const tlogDigestBytes = hexToUint8Array(tlogDigest);
37
+ const bundleDigestBytes = base64ToUint8Array(bundle.messageSignature.messageDigest.digest);
38
+ if (!uint8ArrayEqual(tlogDigestBytes, bundleDigestBytes)) {
39
+ throw new Error("Digest mismatch between TLog entry and bundle");
40
+ }
41
+ }
42
+ // New functionality for HashedRekord v0.0.2 (not in sigstore-js reference, which only supports v0.0.1)
43
+ function verifyHashedRekordV002Body(entry, bundle) {
44
+ const spec = entry.spec.hashedRekordV002;
45
+ if (!bundle.messageSignature) {
46
+ throw new Error("Bundle missing messageSignature for hashedrekord v0.0.2 entry");
47
+ }
48
+ // NOTE: HashedRekord v0.0.2 uses single base64 encoding (unlike intoto which is double-encoded)
49
+ // Verified against Sigstore conformance test suite bundles
50
+ const tlogSig = spec.signature.content || "";
51
+ const tlogSigBytes = base64ToUint8Array(tlogSig);
52
+ const bundleSigBytes = base64ToUint8Array(bundle.messageSignature.signature);
53
+ if (!uint8ArrayEqual(tlogSigBytes, bundleSigBytes)) {
54
+ throw new Error("Signature mismatch between TLog entry and bundle (v0.0.2)");
55
+ }
56
+ const tlogDigest = spec.data.digest || "";
57
+ const tlogDigestBytes = base64ToUint8Array(tlogDigest);
58
+ const bundleDigestBytes = base64ToUint8Array(bundle.messageSignature.messageDigest.digest);
59
+ if (!uint8ArrayEqual(tlogDigestBytes, bundleDigestBytes)) {
60
+ throw new Error("Digest mismatch between TLog entry and bundle (v0.0.2)");
61
+ }
62
+ }
63
+ //# sourceMappingURL=hashedrekord.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hashedrekord.js","sourceRoot":"","sources":["../../src/tlog/hashedrekord.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { SigstoreBundle } from "../bundle.js";
2
+ import type { RekorEntry } from "./body.js";
3
+ export declare function verifyIntotoBody(entry: RekorEntry, bundle: SigstoreBundle): Promise<void>;
4
+ //# sourceMappingURL=intoto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intoto.d.ts","sourceRoot":"","sources":["../../src/tlog/intoto.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAiC5C,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,IAAI,CAAC,CAkDf"}
@@ -0,0 +1,50 @@
1
+ /*
2
+ * Intoto transparency log entry verification
3
+ *
4
+ * Based on sigstore-js:
5
+ * https://github.com/sigstore/sigstore-js/blob/main/packages/verify/src/tlog/intoto.ts
6
+ *
7
+ * Key differences from sigstore-js:
8
+ * - Browser-compatible: uses Uint8Array instead of Buffer for binary data
9
+ * - Direct bundle field comparison instead of SignatureContent abstraction
10
+ * - Uses crypto.subtle.digest for hash computation instead of Node.js crypto
11
+ */
12
+ import { base64Decode, base64ToUint8Array, hexToUint8Array, toArrayBuffer, uint8ArrayEqual } from "../encoding.js";
13
+ import { HashAlgorithms } from "../interfaces.js";
14
+ export async function verifyIntotoBody(entry, bundle) {
15
+ const intotoEntry = entry;
16
+ if (intotoEntry.apiVersion !== "0.0.2") {
17
+ throw new Error(`Unsupported intoto version: ${intotoEntry.apiVersion}`);
18
+ }
19
+ if (!bundle.dsseEnvelope) {
20
+ throw new Error("Bundle missing dsseEnvelope for intoto entry");
21
+ }
22
+ const tlogEnvelope = intotoEntry.spec.content.envelope;
23
+ if (!tlogEnvelope.signatures || tlogEnvelope.signatures.length !== 1) {
24
+ throw new Error("Intoto entry must have exactly one signature");
25
+ }
26
+ // The signature in the intoto tlog entry is double-base64-encoded:
27
+ // 1. Raw signature bytes are base64-encoded (normal)
28
+ // 2. That base64 string is base64-encoded again (for storage in JSON)
29
+ // So we decode twice: base64 -> string -> base64 -> bytes
30
+ const tlogSigBase64 = tlogEnvelope.signatures[0].sig;
31
+ const tlogSigDecoded = base64Decode(tlogSigBase64); // First decode: base64 -> UTF-8 string (which contains base64)
32
+ const tlogSigBytes = base64ToUint8Array(tlogSigDecoded); // Second decode: base64 string -> raw bytes
33
+ if (bundle.dsseEnvelope.signatures.length === 0) {
34
+ throw new Error("Bundle DSSE envelope missing signatures");
35
+ }
36
+ const bundleSigBytes = base64ToUint8Array(bundle.dsseEnvelope.signatures[0].sig);
37
+ if (!uint8ArrayEqual(tlogSigBytes, bundleSigBytes)) {
38
+ throw new Error("Intoto signature mismatch between TLog entry and bundle");
39
+ }
40
+ if (intotoEntry.spec.content.payloadHash) {
41
+ const tlogHash = intotoEntry.spec.content.payloadHash.value;
42
+ const tlogHashBytes = hexToUint8Array(tlogHash);
43
+ const payloadBytes = base64ToUint8Array(bundle.dsseEnvelope.payload);
44
+ const bundleHashBytes = new Uint8Array(await crypto.subtle.digest(HashAlgorithms.SHA256, toArrayBuffer(payloadBytes)));
45
+ if (!uint8ArrayEqual(tlogHashBytes, bundleHashBytes)) {
46
+ throw new Error("Intoto payload hash mismatch between TLog entry and bundle");
47
+ }
48
+ }
49
+ }
50
+ //# sourceMappingURL=intoto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intoto.js","sourceRoot":"","sources":["../../src/tlog/intoto.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACnH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAmClD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,KAAiB,EACjB,MAAsB;IAEtB,MAAM,WAAW,GAAG,KAAoB,CAAC;IAEzC,IAAI,WAAW,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CACb,+BAA+B,WAAW,CAAC,UAAU,EAAE,CACxD,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,YAAY,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;IAEvD,IAAI,CAAC,YAAY,CAAC,UAAU,IAAI,YAAY,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;IAED,mEAAmE;IACnE,qDAAqD;IACrD,sEAAsE;IACtE,0DAA0D;IAC1D,MAAM,aAAa,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACrD,MAAM,cAAc,GAAG,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,+DAA+D;IACnH,MAAM,YAAY,GAAG,kBAAkB,CAAC,cAAc,CAAC,CAAC,CAAC,4CAA4C;IAErG,IAAI,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IAED,MAAM,cAAc,GAAG,kBAAkB,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAEjF,IAAI,CAAC,eAAe,CAAC,YAAY,EAAE,cAAc,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IAED,IAAI,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QACzC,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC;QAC5D,MAAM,aAAa,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;QAEhD,MAAM,YAAY,GAAG,kBAAkB,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QACrE,MAAM,eAAe,GAAG,IAAI,UAAU,CACpC,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC,CAC/E,CAAC;QAEF,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,eAAe,CAAC,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { TLogEntry } from "../bundle.js";
2
+ export declare function verifyMerkleInclusion(entry: TLogEntry): Promise<void>;
3
+ //# sourceMappingURL=merkle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merkle.d.ts","sourceRoot":"","sources":["../../src/tlog/merkle.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAK9C,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,SAAS,GACf,OAAO,CAAC,IAAI,CAAC,CA2Cf"}
@@ -0,0 +1,112 @@
1
+ /*
2
+ Adapted from sigstore-js for browser compatibility:
3
+ https://github.com/sigstore/sigstore-js/blob/main/packages/verify/src/timestamp/merkle.ts
4
+
5
+ Key differences:
6
+ - Uses Uint8Array instead of Buffer
7
+ - Uses async Web Crypto API (crypto.subtle.digest) instead of sync Node.js crypto
8
+ - Base64 decoding via custom base64ToUint8Array instead of Buffer.from
9
+ - Custom uint8ArrayEqual instead of crypto.bufferEqual
10
+ */
11
+ import { base64ToUint8Array, toArrayBuffer, uint8ArrayEqual } from "../encoding.js";
12
+ import { HashAlgorithms } from "../interfaces.js";
13
+ const RFC6962_LEAF_HASH_PREFIX = new Uint8Array([0x00]);
14
+ const RFC6962_NODE_HASH_PREFIX = new Uint8Array([0x01]);
15
+ export async function verifyMerkleInclusion(entry) {
16
+ if (!entry.inclusionProof) {
17
+ throw new Error("Missing inclusion proof");
18
+ }
19
+ const inclusionProof = entry.inclusionProof;
20
+ const logIndex = BigInt(inclusionProof.logIndex);
21
+ const treeSize = BigInt(inclusionProof.treeSize);
22
+ if (logIndex < 0n || logIndex >= treeSize) {
23
+ throw new Error(`Invalid log index: ${logIndex}`);
24
+ }
25
+ // Figure out which subset of hashes corresponds to the inner and border
26
+ // nodes
27
+ const { inner, border } = decompInclProof(logIndex, treeSize);
28
+ if (inclusionProof.hashes.length !== inner + border) {
29
+ throw new Error("Invalid hash count in inclusion proof");
30
+ }
31
+ const innerHashes = inclusionProof.hashes
32
+ .slice(0, inner)
33
+ .map((h) => base64ToUint8Array(h));
34
+ const borderHashes = inclusionProof.hashes
35
+ .slice(inner)
36
+ .map((h) => base64ToUint8Array(h));
37
+ // The entry's hash is the leaf hash
38
+ const leafHash = await hashLeaf(base64ToUint8Array(entry.canonicalizedBody));
39
+ // Chain the hashes belonging to the inner and border portions
40
+ const calculatedHash = await chainBorderRight(await chainInner(leafHash, innerHashes, logIndex), borderHashes);
41
+ const rootHash = base64ToUint8Array(inclusionProof.rootHash);
42
+ // Calculated hash should match the root hash in the inclusion proof
43
+ if (!uint8ArrayEqual(calculatedHash, rootHash)) {
44
+ throw new Error("Calculated root hash does not match inclusion proof");
45
+ }
46
+ }
47
+ // Breaks down inclusion proof for a leaf at the specified index in a tree of
48
+ // the specified size. The split point is where paths to the index leaf and
49
+ // the (size - 1) leaf diverge. Returns lengths of the bottom and upper proof
50
+ // parts.
51
+ function decompInclProof(index, size) {
52
+ const inner = innerProofSize(index, size);
53
+ const border = onesCount(index >> BigInt(inner));
54
+ return { inner, border };
55
+ }
56
+ // Computes a subtree hash for a node on or below the tree's right border.
57
+ // Assumes the provided proof hashes are ordered from lower to higher levels
58
+ // and seed is the initial hash of the node specified by the index.
59
+ async function chainInner(seed, hashes, index) {
60
+ let acc = seed;
61
+ for (let i = 0; i < hashes.length; i++) {
62
+ const h = hashes[i];
63
+ if ((index >> BigInt(i)) & BigInt(1)) {
64
+ acc = await hashChildren(h, acc);
65
+ }
66
+ else {
67
+ acc = await hashChildren(acc, h);
68
+ }
69
+ }
70
+ return acc;
71
+ }
72
+ // Computes a subtree hash for nodes along the tree's right border.
73
+ async function chainBorderRight(seed, hashes) {
74
+ let acc = seed;
75
+ for (const h of hashes) {
76
+ acc = await hashChildren(h, acc);
77
+ }
78
+ return acc;
79
+ }
80
+ function innerProofSize(index, size) {
81
+ return bitLength(index ^ (size - BigInt(1)));
82
+ }
83
+ // Counts the number of ones in the binary representation of the given number.
84
+ // https://en.wikipedia.org/wiki/Hamming_weight
85
+ function onesCount(num) {
86
+ return num.toString(2).split("1").length - 1;
87
+ }
88
+ // Returns the number of bits necessary to represent an integer in binary.
89
+ function bitLength(n) {
90
+ if (n === 0n) {
91
+ return 0;
92
+ }
93
+ return n.toString(2).length;
94
+ }
95
+ // Hashing logic according to RFC6962.
96
+ // https://datatracker.ietf.org/doc/html/rfc6962#section-2
97
+ async function hashChildren(left, right) {
98
+ const data = new Uint8Array(RFC6962_NODE_HASH_PREFIX.length + left.length + right.length);
99
+ data.set(RFC6962_NODE_HASH_PREFIX, 0);
100
+ data.set(left, RFC6962_NODE_HASH_PREFIX.length);
101
+ data.set(right, RFC6962_NODE_HASH_PREFIX.length + left.length);
102
+ const hash = await crypto.subtle.digest(HashAlgorithms.SHA256, toArrayBuffer(data));
103
+ return new Uint8Array(hash);
104
+ }
105
+ async function hashLeaf(leaf) {
106
+ const data = new Uint8Array(RFC6962_LEAF_HASH_PREFIX.length + leaf.length);
107
+ data.set(RFC6962_LEAF_HASH_PREFIX, 0);
108
+ data.set(leaf, RFC6962_LEAF_HASH_PREFIX.length);
109
+ const hash = await crypto.subtle.digest(HashAlgorithms.SHA256, toArrayBuffer(data));
110
+ return new Uint8Array(hash);
111
+ }
112
+ //# sourceMappingURL=merkle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merkle.js","sourceRoot":"","sources":["../../src/tlog/merkle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ "ewogInNpZ25hdHVyZXMiOiBbCiAgewogICAia2V5aWQiOiAiNmYyNjAwODlkNTkyM2RhZjIwMTY2Y2E2NTdjNTQzYWY2MTgzNDZhYjk3MTg4NGE5OTk2MmIwMTk4OGJiZTBjMyIsCiAgICJzaWciOiAiIgogIH0sCiAgewogICAia2V5aWQiOiAiZTcxYTU0ZDU0MzgzNWJhODZhZGFkOTQ2MDM3OWM3NjQxZmI4NzI2ZDE2NGVhNzY2ODAxYTFjNTIyYWJhN2VhMiIsCiAgICJzaWciOiAiMzA0NTAyMjEwMGJiZGRkNDY0ZjgwNjZjZWI4OGJhNzg3Mzc1YzEyY2Q2MzMwNjgwZTA4YzI5MTA3MDNlNjUzOGM3MWNjNzlhZDIwMjIwNTE5MGIwNmU0NTM3ZmU5NjFiM2VmODFmZTY4ZWRjZDAwODljMTlmOTE5YWZlZDQyM2I5YWFmZDcwMDY0MTE1MyIKICB9LAogIHsKICAgImtleWlkIjogIjIyZjRjYWVjNmQ4ZTZmOTU1NWFmNjZiM2Q0YzNjYjA2YTNiYjIzZmRjN2UzOWM5MTZjNjFmNDYyZTZmNTJiMDYiLAogICAic2lnIjogIjMwNDQwMjIwNjkzMDZjZDUyNTdmNzMyYTc0MGMxYWZlNjBhOGU0MzNjNWRlNThlYWZlYWRiZTk5YzMzNmM5YzcxZDE5OGNmODAyMjAwZDc3Mzk1M2FlN2RiYzQ4ZDNlNWJhZDlhNmY2NGJhZmZmMTk2YjdlMmFkNGE1MmExOTUxOTM2N2Q0N2RjMDQyIgogIH0sCiAgewogICAia2V5aWQiOiAiNjE2NDM4MzgxMjViNDQwYjQwZGI2OTQyZjVjYjVhMzFjMGRjMDQzNjgzMTZlYjJhYWE1OGI5NTkwNGE1ODIyMiIsCiAgICJzaWciOiAiMzA0NDAyMjA0ZDIxYTJlYzgwZGY2NmU2MWY2ZmUyOTEyOTUxZGM0N2RmODM2MDM2ZjhjMGFiMTA4MTZkMzc1ZTcxZGJmNzllMDIyMDU0N2FkY2UxYWZkZjA0ZTY3OTRlZmEyMDNkZDUyNjRjNmY3ZTBlZjc4ZTU3ZmU5MzRiMGQyNmNiOTk0ZWVjNzYiCiAgfSwKICB7CiAgICJrZXlpZCI6ICJhNjg3ZTViZjRmYWI4MmIwZWU1OGQ0NmUwNWM5NTM1MTQ1YTJjOWFmYjQ1OGY0M2Q0MmI0NWNhMGZkY2UyYTcwIiwKICAgInNpZyI6ICIzMDQ1MDIyMDYwODI2NDk2NTU3MTQ0ZWIxNjQ5ODkzZWQ1ZjZmNGVhNTQ1MzZmZWIwY2E4MmY4Yjg5YWU2NDFiZTM5NzQzZTUwMjIxMDBhZDcxMThiNWU5ZDQ4MzczMjYyMDZlNDEyZmM2ZGEyOTk5OTI1ZDExMDMyOGE3YzE2NmIwNmM2MjQzMzZjOTNmIgogIH0sCiAgewogICAia2V5aWQiOiAiMTgzZTY0ZjM3NjcwZGMxM2NhMGQyODk5NWEzMDUzZjM3NDA5NTRkZGNlNDQzMjFhNDFlNDY1MzRjZjQ0ZTYzMiIsCiAgICJzaWciOiAiMzA0NjAyMjEwMGQ4MTc5NDM5YzJlNzNlYjBjMTczM2FiZWU3ZmFmODMyZGNhZWE3MjYzZWRjYjQ5MTk4OTFjM2EyNDdmMDU5MjMwMjIxMDBlMWE0MzdlMDc5N2U4MDNmOWI3MmRjOWQyZDkyMTU1YjBhMjI3MGMyNGVmZGQ1ZjRiM2E1ZDhmMGIwZjQzMWE3IgogIH0KIF0sCiAic2lnbmVkIjogewogICJfdHlwZSI6ICJyb290IiwKICAiY29uc2lzdGVudF9zbmFwc2hvdCI6IHRydWUsCiAgImV4cGlyZXMiOiAiMjAyNi0wMS0yMlQxMzowNTo1OVoiLAogICJrZXlzIjogewogICAiMGM4NzQzMmMzYmYwOWZkOTkxODlmZGMzMmZhNWVhZWRmNGU0YTVmYWM3YmFiNzNmYTA0YTJlMGZjNjRhZjZmNSI6IHsKICAgICJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCiAgICAgInNoYTI1NiIsCiAgICAgInNoYTUxMiIKICAgIF0sCiAgICAia2V5dHlwZSI6ICJlY2RzYSIsCiAgICAia2V5dmFsIjogewogICAgICJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRVdSaUdyNStqKzNKNVNzSCtadHI1bkUySDJ3TzdcbkJWK25PM3M5M2dMY2ExOHFUT3pIWTFvV3lBR0R5a01Tc0dUVUJTdDlEK0FuMEtmS3NEMm1mU000MlE9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCiAgICB9LAogICAgInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKICAgICJ4LXR1Zi1vbi1jaS1vbmxpbmUtdXJpIjogImdjcGttczpwcm9qZWN0cy9zaWdzdG9yZS1yb290LXNpZ25pbmcvbG9jYXRpb25zL2dsb2JhbC9rZXlSaW5ncy9yb290L2NyeXB0b0tleXMvdGltZXN0YW1wL2NyeXB0b0tleVZlcnNpb25zLzEiCiAgIH0sCiAgICIxODNlNjRmMzc2NzBkYzEzY2EwZDI4OTk1YTMwNTNmMzc0MDk1NGRkY2U0NDMyMWE0MWU0NjUzNGNmNDRlNjMyIjogewogICAgImtleXR5cGUiOiAiZWNkc2EiLAogICAgImtleXZhbCI6IHsKICAgICAicHVibGljIjogIi0tLS0tQkVHSU4gUFVCTElDIEtFWS0tLS0tXG5NRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVNeHBQT0pDSVo1b3RHNDEwNmZHSnNlRVFpM1Y5XG5wa01ZUTR1eVY5VGoxTTdXSFhJeUxHK2prZnZ1RzBnbFExSlpiUlpaQlYzZ0FSNHNvamRHSElTZW93PT1cbi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLVxuIgogICAgfSwKICAgICJzY2hlbWUiOiAiZWNkc2Etc2hhMi1uaXN0cDI1NiIsCiAgICAieC10dWYtb24tY2kta2V5b3duZXIiOiAiQGxhbmNlIgogICB9LAogICAiMjJmNGNhZWM2ZDhlNmY5NTU1YWY2NmIzZDRjM2NiMDZhM2JiMjNmZGM3ZTM5YzkxNmM2MWY0NjJlNmY1MmIwNiI6IHsKICAgICJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCiAgICAgInNoYTI1NiIsCiAgICAgInNoYTUxMiIKICAgIF0sCiAgICAia2V5dHlwZSI6ICJlY2RzYSIsCiAgICAia2V5dmFsIjogewogICAgICJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXpCelZPbUhDUG9qTVZMU0kzNjRXaWlWOE5QckRcbjZJZ1J4Vmxpc2t6L3YreTNKRVI1bWNWR2NPTmxpRGNXTUM1SjJsZkhtalBOUGhiNEg3eG04THpmU0E9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCiAgICB9LAogICAgInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKICAgICJ4LXR1Zi1vbi1jaS1rZXlvd25lciI6ICJAc2FudGlhZ290b3JyZXMiCiAgIH0sCiAgICI2MTY0MzgzODEyNWI0NDBiNDBkYjY5NDJmNWNiNWEzMWMwZGMwNDM2ODMxNmViMmFhYTU4Yjk1OTA0YTU4MjIyIjogewogICAgImtleWlkX2hhc2hfYWxnb3JpdGhtcyI6IFsKICAgICAic2hhMjU2IiwKICAgICAic2hhNTEyIgogICAgXSwKICAgICJrZXl0eXBlIjogImVjZHNhIiwKICAgICJrZXl2YWwiOiB7CiAgICAgInB1YmxpYyI6ICItLS0tLUJFR0lOIFBVQkxJQyBLRVktLS0tLVxuTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFaW5pa1NzQVFtWWtOZUg1ZVlxL0NuSXpMYWFjT1xueGxTYWF3UURPd3FLeS90Q3F4cTV4eFBTSmMyMUs0V0loczlHeU9rS2Z6dWVZM0dJTHpjTUpaNGNXdz09XG4tLS0tLUVORCBQVUJMSUMgS0VZLS0tLS1cbiIKICAgIH0sCiAgICAic2NoZW1lIjogImVjZHNhLXNoYTItbmlzdHAyNTYiLAogICAgIngtdHVmLW9uLWNpLWtleW93bmVyIjogIkBib2JjYWxsYXdheSIKICAgfSwKICAgImE2ODdlNWJmNGZhYjgyYjBlZTU4ZDQ2ZTA1Yzk1MzUxNDVhMmM5YWZiNDU4ZjQzZDQyYjQ1Y2EwZmRjZTJhNzAiOiB7CiAgICAia2V5aWRfaGFzaF9hbGdvcml0aG1zIjogWwogICAgICJzaGEyNTYiLAogICAgICJzaGE1MTIiCiAgICBdLAogICAgImtleXR5cGUiOiAiZWNkc2EiLAogICAgImtleXZhbCI6IHsKICAgICAicHVibGljIjogIi0tLS0tQkVHSU4gUFVCTElDIEtFWS0tLS0tXG5NRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUUwZ2hyaDkyTHcxWXIzaWRHVjVXcUN0TURCOEN4XG4rRDhoZEM0dzJaTE5JcGxWUm9WR0xza1lhM2doZU15T2ppSjhrUGkxNWFRMi8vN1Arb2o3VXZKUEd3PT1cbi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLVxuIgogICAgfSwKICAgICJzY2hlbWUiOiAiZWNkc2Etc2hhMi1uaXN0cDI1NiIsCiAgICAieC10dWYtb24tY2kta2V5b3duZXIiOiAiQGpvc2h1YWdsIgogICB9LAogICAiZTcxYTU0ZDU0MzgzNWJhODZhZGFkOTQ2MDM3OWM3NjQxZmI4NzI2ZDE2NGVhNzY2ODAxYTFjNTIyYWJhN2VhMiI6IHsKICAgICJrZXlpZF9oYXNoX2FsZ29yaXRobXMiOiBbCiAgICAgInNoYTI1NiIsCiAgICAgInNoYTUxMiIKICAgIF0sCiAgICAia2V5dHlwZSI6ICJlY2RzYSIsCiAgICAia2V5dmFsIjogewogICAgICJwdWJsaWMiOiAiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRUVYc3ozU1pYRmI4ak1WNDJqNnBKbHlqYmpSOEtcbk4zQndvY2V4cTZMTUliNXFzV0tPUXZMTjE2TlVlZkxjNEhzd09vdW1Sc1ZWYWFqU3BRUzZmb2JrUnc9PVxuLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tXG4iCiAgICB9LAogICAgInNjaGVtZSI6ICJlY2RzYS1zaGEyLW5pc3RwMjU2IiwKICAgICJ4LXR1Zi1vbi1jaS1rZXlvd25lciI6ICJAbW5tNjc4IgogICB9CiAgfSwKICAicm9sZXMiOiB7CiAgICJyb290IjogewogICAgImtleWlkcyI6IFsKICAgICAiZTcxYTU0ZDU0MzgzNWJhODZhZGFkOTQ2MDM3OWM3NjQxZmI4NzI2ZDE2NGVhNzY2ODAxYTFjNTIyYWJhN2VhMiIsCiAgICAgIjIyZjRjYWVjNmQ4ZTZmOTU1NWFmNjZiM2Q0YzNjYjA2YTNiYjIzZmRjN2UzOWM5MTZjNjFmNDYyZTZmNTJiMDYiLAogICAgICI2MTY0MzgzODEyNWI0NDBiNDBkYjY5NDJmNWNiNWEzMWMwZGMwNDM2ODMxNmViMmFhYTU4Yjk1OTA0YTU4MjIyIiwKICAgICAiYTY4N2U1YmY0ZmFiODJiMGVlNThkNDZlMDVjOTUzNTE0NWEyYzlhZmI0NThmNDNkNDJiNDVjYTBmZGNlMmE3MCIsCiAgICAgIjE4M2U2NGYzNzY3MGRjMTNjYTBkMjg5OTVhMzA1M2YzNzQwOTU0ZGRjZTQ0MzIxYTQxZTQ2NTM0Y2Y0NGU2MzIiCiAgICBdLAogICAgInRocmVzaG9sZCI6IDMKICAgfSwKICAgInNuYXBzaG90IjogewogICAgImtleWlkcyI6IFsKICAgICAiMGM4NzQzMmMzYmYwOWZkOTkxODlmZGMzMmZhNWVhZWRmNGU0YTVmYWM3YmFiNzNmYTA0YTJlMGZjNjRhZjZmNSIKICAgIF0sCiAgICAidGhyZXNob2xkIjogMSwKICAgICJ4LXR1Zi1vbi1jaS1leHBpcnktcGVyaW9kIjogMzY1MCwKICAgICJ4LXR1Zi1vbi1jaS1zaWduaW5nLXBlcmlvZCI6IDM2NQogICB9LAogICAidGFyZ2V0cyI6IHsKICAgICJrZXlpZHMiOiBbCiAgICAgImU3MWE1NGQ1NDM4MzViYTg2YWRhZDk0NjAzNzljNzY0MWZiODcyNmQxNjRlYTc2NjgwMWExYzUyMmFiYTdlYTIiLAogICAgICIyMmY0Y2FlYzZkOGU2Zjk1NTVhZjY2YjNkNGMzY2IwNmEzYmIyM2ZkYzdlMzljOTE2YzYxZjQ2MmU2ZjUyYjA2IiwKICAgICAiNjE2NDM4MzgxMjViNDQwYjQwZGI2OTQyZjVjYjVhMzFjMGRjMDQzNjgzMTZlYjJhYWE1OGI5NTkwNGE1ODIyMiIsCiAgICAgImE2ODdlNWJmNGZhYjgyYjBlZTU4ZDQ2ZTA1Yzk1MzUxNDVhMmM5YWZiNDU4ZjQzZDQyYjQ1Y2EwZmRjZTJhNzAiLAogICAgICIxODNlNjRmMzc2NzBkYzEzY2EwZDI4OTk1YTMwNTNmMzc0MDk1NGRkY2U0NDMyMWE0MWU0NjUzNGNmNDRlNjMyIgogICAgXSwKICAgICJ0aHJlc2hvbGQiOiAzCiAgIH0sCiAgICJ0aW1lc3RhbXAiOiB7CiAgICAia2V5aWRzIjogWwogICAgICIwYzg3NDMyYzNiZjA5ZmQ5OTE4OWZkYzMyZmE1ZWFlZGY0ZTRhNWZhYzdiYWI3M2ZhMDRhMmUwZmM2NGFmNmY1IgogICAgXSwKICAgICJ0aHJlc2hvbGQiOiAxLAogICAgIngtdHVmLW9uLWNpLWV4cGlyeS1wZXJpb2QiOiA3LAogICAgIngtdHVmLW9uLWNpLXNpZ25pbmctcGVyaW9kIjogNgogICB9CiAgfSwKICAic3BlY192ZXJzaW9uIjogIjEuMCIsCiAgInZlcnNpb24iOiAxMywKICAieC10dWYtb24tY2ktZXhwaXJ5LXBlcmlvZCI6IDE5NywKICAieC10dWYtb24tY2ktc2lnbmluZy1wZXJpb2QiOiA0NgogfQp9"
@@ -0,0 +1,95 @@
1
+ import type { TrustedRoot } from "../interfaces.js";
2
+ /**
3
+ * Options for TrustedRootProvider configuration
4
+ */
5
+ export interface TrustedRootProviderOptions {
6
+ /**
7
+ * TUF repository URL for metadata
8
+ * Default: Sigstore production TUF repository
9
+ */
10
+ metadataUrl?: string;
11
+ /**
12
+ * Target base URL for fetching target files
13
+ * If not specified, uses the same as metadataUrl
14
+ */
15
+ targetBaseUrl?: string;
16
+ /**
17
+ * Initial root metadata (1.root.json content)
18
+ * If not provided, will use embedded default
19
+ */
20
+ initialRoot?: string;
21
+ /**
22
+ * Namespace for TUF cache storage
23
+ * Default: 'sigstore-browser'
24
+ */
25
+ namespace?: string;
26
+ /**
27
+ * Name of the trusted root target file
28
+ * Default: 'trusted_root.json'
29
+ */
30
+ trustedRootTarget?: string;
31
+ /**
32
+ * Cache TTL in milliseconds
33
+ * Default: 1 hour (3600000 ms)
34
+ */
35
+ cacheTTL?: number;
36
+ }
37
+ /**
38
+ * Provides Sigstore trusted root via TUF for secure updates
39
+ *
40
+ * This class manages fetching and caching of Sigstore trusted root metadata
41
+ * using The Update Framework (TUF) for secure, verified updates.
42
+ *
43
+ * Example usage:
44
+ * ```typescript
45
+ * const provider = new TrustedRootProvider();
46
+ * const trustedRoot = await provider.getTrustedRoot();
47
+ * ```
48
+ */
49
+ export declare class TrustedRootProvider {
50
+ private metadataUrl;
51
+ private targetBaseUrl?;
52
+ private initialRoot?;
53
+ private namespace;
54
+ private trustedRootTarget;
55
+ private cacheTTL;
56
+ private tufClient?;
57
+ private cachedRoot?;
58
+ private cacheTimestamp?;
59
+ constructor(options?: TrustedRootProviderOptions);
60
+ /**
61
+ * Initialize the TUF client
62
+ * Lazy initialization to avoid loading TUF client until needed
63
+ */
64
+ private initTUFClient;
65
+ /**
66
+ * Get the default embedded root metadata
67
+ * Returns the TUF root.json that bootstraps the TUF client
68
+ */
69
+ private getDefaultRoot;
70
+ /**
71
+ * Check if cached trusted root is still valid
72
+ */
73
+ private isCacheValid;
74
+ /**
75
+ * Get the Sigstore trusted root metadata
76
+ * Uses TUF to securely fetch and verify the trusted root
77
+ *
78
+ * @returns Promise<TrustedRoot> The verified trusted root metadata
79
+ * @throws Error if TUF verification fails or root cannot be fetched
80
+ */
81
+ getTrustedRoot(): Promise<TrustedRoot>;
82
+ /**
83
+ * Manually refresh the trusted root from TUF
84
+ * Bypasses cache and forces a fresh fetch
85
+ *
86
+ * @returns Promise<TrustedRoot> The updated trusted root metadata
87
+ */
88
+ refreshTrustedRoot(): Promise<TrustedRoot>;
89
+ /**
90
+ * Clear the cached trusted root
91
+ * Next call to getTrustedRoot() will fetch fresh data
92
+ */
93
+ clearCache(): void;
94
+ }
95
+ //# sourceMappingURL=tuf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tuf.d.ts","sourceRoot":"","sources":["../../src/trust/tuf.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIpD;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAYD;;;;;;;;;;;GAWG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAS;IAEzB,OAAO,CAAC,SAAS,CAAC,CAAY;IAC9B,OAAO,CAAC,UAAU,CAAC,CAAc;IACjC,OAAO,CAAC,cAAc,CAAC,CAAS;gBAEpB,OAAO,GAAE,0BAA+B;IAUpD;;;OAGG;YACW,aAAa;IAwB3B;;;OAGG;YACW,cAAc;IAY5B;;OAEG;IACH,OAAO,CAAC,YAAY;IASpB;;;;;;OAMG;IACG,cAAc,IAAI,OAAO,CAAC,WAAW,CAAC;IAsC5C;;;;;OAKG;IACG,kBAAkB,IAAI,OAAO,CAAC,WAAW,CAAC;IAShD;;;OAGG;IACH,UAAU,IAAI,IAAI;CAInB"}
@@ -0,0 +1,150 @@
1
+ /*
2
+ * TUF (The Update Framework) integration for trusted root management
3
+ *
4
+ * Provides secure updates for Sigstore trusted root metadata using TUF.
5
+ * Uses tuf-browser for browser-compatible TUF client functionality.
6
+ *
7
+ * Reference: https://github.com/freedomofpress/tuf-browser
8
+ */
9
+ import { Uint8ArrayToString } from "../encoding.js";
10
+ /**
11
+ * Default configuration for Sigstore production TUF repository
12
+ */
13
+ const DEFAULT_CONFIG = {
14
+ metadataUrl: 'https://tuf-repo-cdn.sigstore.dev/',
15
+ namespace: 'sigstore-browser',
16
+ trustedRootTarget: 'trusted_root.json',
17
+ cacheTTL: 3600000, // 1 hour
18
+ };
19
+ /**
20
+ * Provides Sigstore trusted root via TUF for secure updates
21
+ *
22
+ * This class manages fetching and caching of Sigstore trusted root metadata
23
+ * using The Update Framework (TUF) for secure, verified updates.
24
+ *
25
+ * Example usage:
26
+ * ```typescript
27
+ * const provider = new TrustedRootProvider();
28
+ * const trustedRoot = await provider.getTrustedRoot();
29
+ * ```
30
+ */
31
+ export class TrustedRootProvider {
32
+ metadataUrl;
33
+ targetBaseUrl;
34
+ initialRoot;
35
+ namespace;
36
+ trustedRootTarget;
37
+ cacheTTL;
38
+ tufClient;
39
+ cachedRoot;
40
+ cacheTimestamp;
41
+ constructor(options = {}) {
42
+ const metadataUrl = options.metadataUrl || DEFAULT_CONFIG.metadataUrl;
43
+ this.metadataUrl = metadataUrl.endsWith('/') ? metadataUrl : `${metadataUrl}/`;
44
+ this.targetBaseUrl = options.targetBaseUrl || this.metadataUrl;
45
+ this.initialRoot = options.initialRoot;
46
+ this.namespace = options.namespace || DEFAULT_CONFIG.namespace;
47
+ this.trustedRootTarget = options.trustedRootTarget || DEFAULT_CONFIG.trustedRootTarget;
48
+ this.cacheTTL = options.cacheTTL ?? DEFAULT_CONFIG.cacheTTL;
49
+ }
50
+ /**
51
+ * Initialize the TUF client
52
+ * Lazy initialization to avoid loading TUF client until needed
53
+ */
54
+ async initTUFClient() {
55
+ if (this.tufClient) {
56
+ return;
57
+ }
58
+ try {
59
+ const { TUFClient } = await import('tuf-browser/dist/tuf.js');
60
+ // Get initial root metadata
61
+ const rootMetadata = this.initialRoot || await this.getDefaultRoot();
62
+ this.tufClient = new TUFClient(this.metadataUrl, rootMetadata, this.namespace, this.targetBaseUrl);
63
+ }
64
+ catch (error) {
65
+ throw new Error(`Failed to initialize TUF client: ${error instanceof Error ? error.message : String(error)}`);
66
+ }
67
+ }
68
+ /**
69
+ * Get the default embedded root metadata
70
+ * Returns the TUF root.json that bootstraps the TUF client
71
+ */
72
+ async getDefaultRoot() {
73
+ // Import the embedded TUF root metadata (base64-encoded 1.root.json as JSON string)
74
+ // This is the root of trust for TUF, not to be confused with the Sigstore trusted root
75
+ const tufRootModule = await import('./tuf-root.json', { with: { type: 'json' } });
76
+ const tufRootBase64 = tufRootModule.default;
77
+ // Decode from base64 to get the actual root.json content
78
+ const decoder = new TextDecoder();
79
+ const rootBytes = Uint8Array.from(atob(tufRootBase64), c => c.charCodeAt(0));
80
+ return decoder.decode(rootBytes);
81
+ }
82
+ /**
83
+ * Check if cached trusted root is still valid
84
+ */
85
+ isCacheValid() {
86
+ if (!this.cachedRoot || !this.cacheTimestamp) {
87
+ return false;
88
+ }
89
+ const now = Date.now();
90
+ return (now - this.cacheTimestamp) < this.cacheTTL;
91
+ }
92
+ /**
93
+ * Get the Sigstore trusted root metadata
94
+ * Uses TUF to securely fetch and verify the trusted root
95
+ *
96
+ * @returns Promise<TrustedRoot> The verified trusted root metadata
97
+ * @throws Error if TUF verification fails or root cannot be fetched
98
+ */
99
+ async getTrustedRoot() {
100
+ // Return cached root if still valid
101
+ if (this.isCacheValid() && this.cachedRoot) {
102
+ return this.cachedRoot;
103
+ }
104
+ // Initialize TUF client if needed
105
+ await this.initTUFClient();
106
+ if (!this.tufClient) {
107
+ throw new Error('TUF client not initialized');
108
+ }
109
+ try {
110
+ // Update TUF metadata (root, timestamp, snapshot, targets)
111
+ // This must be called before getTarget() to populate the metadata cache
112
+ await this.tufClient.updateTUF();
113
+ // Fetch the trusted root target via TUF
114
+ // TUF will handle all verification (signatures, rollback protection, etc.)
115
+ const trustedRootBytes = await this.tufClient.getTarget(this.trustedRootTarget);
116
+ // Parse the trusted root JSON
117
+ const trustedRootJson = Uint8ArrayToString(trustedRootBytes);
118
+ const trustedRoot = JSON.parse(trustedRootJson);
119
+ // Cache the result
120
+ this.cachedRoot = trustedRoot;
121
+ this.cacheTimestamp = Date.now();
122
+ return trustedRoot;
123
+ }
124
+ catch (error) {
125
+ throw new Error(`Failed to fetch trusted root via TUF: ${error instanceof Error ? error.message : String(error)}`);
126
+ }
127
+ }
128
+ /**
129
+ * Manually refresh the trusted root from TUF
130
+ * Bypasses cache and forces a fresh fetch
131
+ *
132
+ * @returns Promise<TrustedRoot> The updated trusted root metadata
133
+ */
134
+ async refreshTrustedRoot() {
135
+ // Clear cache
136
+ this.cachedRoot = undefined;
137
+ this.cacheTimestamp = undefined;
138
+ // Fetch fresh root
139
+ return await this.getTrustedRoot();
140
+ }
141
+ /**
142
+ * Clear the cached trusted root
143
+ * Next call to getTrustedRoot() will fetch fresh data
144
+ */
145
+ clearCache() {
146
+ this.cachedRoot = undefined;
147
+ this.cacheTimestamp = undefined;
148
+ }
149
+ }
150
+ //# sourceMappingURL=tuf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tuf.js","sourceRoot":"","sources":["../../src/trust/tuf.ts"],"names":[],"mappings":"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"}