privateer-agent 0.15.4 → 0.15.6
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/README.md +11 -0
- package/bin/boot-bundle.d.mts +2 -0
- package/bin/boot-bundle.mjs +44 -0
- package/bin/fresh-supervisor.d.mts +5 -1
- package/bin/fresh-supervisor.mjs +47 -10
- package/bin/privateer-launch.mjs +27 -3
- package/bin/privateer-subagent.mjs +5 -2
- package/bin/privateer-verify.mjs +12 -0
- package/bin/session-recovery.d.mts +53 -0
- package/bin/session-recovery.mjs +240 -0
- package/bin/session-seal-preload.mjs +17 -0
- package/bin/session-seal.d.mts +25 -0
- package/bin/session-seal.mjs +242 -0
- package/dist-boot/boot.mjs +3 -0
- package/dist-boot/c-27JKSMWL.mjs +1460 -0
- package/dist-boot/c-2BMRFV24.mjs +269 -0
- package/dist-boot/c-2CTF6JA3.mjs +166 -0
- package/dist-boot/c-2G3BBHRJ.mjs +84 -0
- package/dist-boot/c-2IDLKXX6.mjs +250 -0
- package/dist-boot/c-2NJD5VYM.mjs +8 -0
- package/dist-boot/c-2S5EEQPW.mjs +1602 -0
- package/dist-boot/c-2WRDCUVI.mjs +25 -0
- package/dist-boot/c-2YN3M256.mjs +14 -0
- package/dist-boot/c-37GM3GMU.mjs +187 -0
- package/dist-boot/c-3STKRSVO.mjs +2480 -0
- package/dist-boot/c-3TPV6TQQ.mjs +2320 -0
- package/dist-boot/c-3UVHLQDJ.mjs +225 -0
- package/dist-boot/c-42PUUZYC.mjs +697 -0
- package/dist-boot/c-4D5UMWVW.mjs +683 -0
- package/dist-boot/c-4ETZRMTA.mjs +46 -0
- package/dist-boot/c-4QT25BD5.mjs +1482 -0
- package/dist-boot/c-4WVR32AP.mjs +2579 -0
- package/dist-boot/c-5EMM567G.mjs +152 -0
- package/dist-boot/c-5FA4CV63.mjs +145 -0
- package/dist-boot/c-5GV3X3RB.mjs +14 -0
- package/dist-boot/c-5JCEPRIY.mjs +52 -0
- package/dist-boot/c-5NDKIIWT.mjs +16 -0
- package/dist-boot/c-5QL3AR26.mjs +4665 -0
- package/dist-boot/c-5XY6MFKN.mjs +5142 -0
- package/dist-boot/c-65UZIZC7.mjs +2897 -0
- package/dist-boot/c-6FUXKHOK.mjs +1969 -0
- package/dist-boot/c-6JHWQE4V.mjs +18242 -0
- package/dist-boot/c-6LOBR4I6.mjs +5280 -0
- package/dist-boot/c-6QHOZXKQ.mjs +14394 -0
- package/dist-boot/c-6ZO2SADQ.mjs +178 -0
- package/dist-boot/c-6ZORVVZP.mjs +1449 -0
- package/dist-boot/c-76QH4UCP.mjs +2441 -0
- package/dist-boot/c-77GO5L5Y.mjs +20982 -0
- package/dist-boot/c-7M23XFTN.mjs +5052 -0
- package/dist-boot/c-7TC367E2.mjs +32 -0
- package/dist-boot/c-7UOG7POX.mjs +1524 -0
- package/dist-boot/c-7VHP3FLN.mjs +376 -0
- package/dist-boot/c-A73JHZP2.mjs +13207 -0
- package/dist-boot/c-ABXULAFL.mjs +71 -0
- package/dist-boot/c-ANDD2AQO.mjs +74 -0
- package/dist-boot/c-AOY77AZL.mjs +1430 -0
- package/dist-boot/c-AXEPZ22I.mjs +108 -0
- package/dist-boot/c-B2Y7VNHU.mjs +427 -0
- package/dist-boot/c-B7VJUH73.mjs +77 -0
- package/dist-boot/c-BFW6CDVL.mjs +24 -0
- package/dist-boot/c-BHNIF2AR.mjs +188 -0
- package/dist-boot/c-BKF2O6BL.mjs +23 -0
- package/dist-boot/c-BOZXFTZN.mjs +8 -0
- package/dist-boot/c-BRNYJWZL.mjs +28 -0
- package/dist-boot/c-C3N4Z2HO.mjs +93 -0
- package/dist-boot/c-C4IV7ZFG.mjs +717 -0
- package/dist-boot/c-C5NK6UYV.mjs +793 -0
- package/dist-boot/c-C67644MB.mjs +1659 -0
- package/dist-boot/c-C6S2YB53.mjs +620 -0
- package/dist-boot/c-CDBEJSBF.mjs +37 -0
- package/dist-boot/c-CG47HBKU.mjs +435 -0
- package/dist-boot/c-CKCTWCT5.mjs +51 -0
- package/dist-boot/c-CN77DCGF.mjs +60 -0
- package/dist-boot/c-CRBXNKFO.mjs +1795 -0
- package/dist-boot/c-CRIHASQ6.mjs +973 -0
- package/dist-boot/c-CU4NGAUO.mjs +3786 -0
- package/dist-boot/c-CWRFLGQU.mjs +1883 -0
- package/dist-boot/c-CYQB2USO.mjs +32 -0
- package/dist-boot/c-DEE67DJO.mjs +379 -0
- package/dist-boot/c-DIFDBYOP.mjs +1258 -0
- package/dist-boot/c-DOSGVXDZ.mjs +34879 -0
- package/dist-boot/c-DR7XQI32.mjs +381 -0
- package/dist-boot/c-DTGPSB46.mjs +14666 -0
- package/dist-boot/c-DTHDNA4P.mjs +320 -0
- package/dist-boot/c-E4Z3Y5B5.mjs +3864 -0
- package/dist-boot/c-E66Z2TI7.mjs +203 -0
- package/dist-boot/c-EBU6RLRV.mjs +1527 -0
- package/dist-boot/c-EBZZNGSF.mjs +432 -0
- package/dist-boot/c-EC3LJ2KF.mjs +1032 -0
- package/dist-boot/c-EQBKXWNX.mjs +15829 -0
- package/dist-boot/c-EUEPIW4S.mjs +574 -0
- package/dist-boot/c-EX4YVWAT.mjs +378 -0
- package/dist-boot/c-EYZGSAJU.mjs +98 -0
- package/dist-boot/c-F75VRKY4.mjs +172 -0
- package/dist-boot/c-FH4NXKHV.mjs +177 -0
- package/dist-boot/c-FHNUCTEM.mjs +140 -0
- package/dist-boot/c-FJ5T42DS.mjs +5349 -0
- package/dist-boot/c-FPCNRL7G.mjs +1728 -0
- package/dist-boot/c-G4DLN7Q4.mjs +8 -0
- package/dist-boot/c-G56GYQFZ.mjs +2507 -0
- package/dist-boot/c-GLIOERDQ.mjs +1200 -0
- package/dist-boot/c-GMJ5HUBM.mjs +14 -0
- package/dist-boot/c-H3HSGMAQ.mjs +461 -0
- package/dist-boot/c-HIKTO6P7.mjs +275 -0
- package/dist-boot/c-I2MCJ34O.mjs +464 -0
- package/dist-boot/c-I3C6LBW4.mjs +765 -0
- package/dist-boot/c-I54OKQHW.mjs +387 -0
- package/dist-boot/c-IFSP3R4D.mjs +80 -0
- package/dist-boot/c-IZK77VB7.mjs +171 -0
- package/dist-boot/c-J3Y25UGE.mjs +54 -0
- package/dist-boot/c-J5IESS7W.mjs +27750 -0
- package/dist-boot/c-JJWZBY7L.mjs +254 -0
- package/dist-boot/c-JKTFXTGF.mjs +463 -0
- package/dist-boot/c-JN57AXQ4.mjs +77 -0
- package/dist-boot/c-KFIO6LUW.mjs +1096 -0
- package/dist-boot/c-KIEMEFWW.mjs +478 -0
- package/dist-boot/c-KIVXWBYD.mjs +28 -0
- package/dist-boot/c-KP6CRIP4.mjs +580 -0
- package/dist-boot/c-L26VOJX4.mjs +11558 -0
- package/dist-boot/c-L5GHWG5G.mjs +5988 -0
- package/dist-boot/c-M7NSQAKK.mjs +353 -0
- package/dist-boot/c-MCEWOPBW.mjs +56 -0
- package/dist-boot/c-MGPIEG7I.mjs +20 -0
- package/dist-boot/c-NREXJV3M.mjs +393 -0
- package/dist-boot/c-O5PP6CTX.mjs +162 -0
- package/dist-boot/c-OBQDHSXM.mjs +1774 -0
- package/dist-boot/c-OLQHHDD4.mjs +21 -0
- package/dist-boot/c-OXW4JQQH.mjs +319 -0
- package/dist-boot/c-P3D7ZUWN.mjs +1288 -0
- package/dist-boot/c-P4PQZVV5.mjs +948 -0
- package/dist-boot/c-P63T3XL2.mjs +26373 -0
- package/dist-boot/c-P6N5DQGZ.mjs +194 -0
- package/dist-boot/c-P7MLKQFC.mjs +58 -0
- package/dist-boot/c-PB3PZJL5.mjs +1276 -0
- package/dist-boot/c-PTN4S6G2.mjs +1259 -0
- package/dist-boot/c-PYCE5J7U.mjs +1083 -0
- package/dist-boot/c-Q4HYCRLB.mjs +19410 -0
- package/dist-boot/c-QUXMETGG.mjs +68 -0
- package/dist-boot/c-RDMJZCOX.mjs +356 -0
- package/dist-boot/c-ROGJK76M.mjs +17 -0
- package/dist-boot/c-RQJJ26T4.mjs +708 -0
- package/dist-boot/c-RSKCUPJF.mjs +7559 -0
- package/dist-boot/c-RVJU4O6P.mjs +37 -0
- package/dist-boot/c-S2RVHR3M.mjs +165 -0
- package/dist-boot/c-SKMK3PEE.mjs +91120 -0
- package/dist-boot/c-TI7SM4EG.mjs +20 -0
- package/dist-boot/c-TILJ6GXD.mjs +1235 -0
- package/dist-boot/c-TT6BCUJD.mjs +114 -0
- package/dist-boot/c-U4ITOXAN.mjs +2107 -0
- package/dist-boot/c-UGERXVO2.mjs +7120 -0
- package/dist-boot/c-UPBH5AXY.mjs +1363 -0
- package/dist-boot/c-US2PUNZL.mjs +597 -0
- package/dist-boot/c-UU4WZPPE.mjs +20 -0
- package/dist-boot/c-UWVIYPQS.mjs +39 -0
- package/dist-boot/c-V4RHQBPQ.mjs +17683 -0
- package/dist-boot/c-V5MRVK47.mjs +351 -0
- package/dist-boot/c-V6CL266R.mjs +1755 -0
- package/dist-boot/c-VJTMFKYE.mjs +14975 -0
- package/dist-boot/c-VJTRUKIB.mjs +773 -0
- package/dist-boot/c-W4IFSHPW.mjs +43 -0
- package/dist-boot/c-WETGB2CF.mjs +113 -0
- package/dist-boot/c-WO3QSZUU.mjs +1337 -0
- package/dist-boot/c-WQLH73TY.mjs +242 -0
- package/dist-boot/c-XL735JW5.mjs +500 -0
- package/dist-boot/c-Y7HADL5B.mjs +1107 -0
- package/dist-boot/c-YGQHSVSK.mjs +41 -0
- package/dist-boot/c-YMP2AMEB.mjs +10350 -0
- package/dist-boot/c-YRDO2WEF.mjs +12012 -0
- package/dist-boot/c-YUSTRATJ.mjs +8 -0
- package/dist-boot/c-Z2262R22.mjs +2697 -0
- package/dist-boot/c-Z4ALQMJC.mjs +709 -0
- package/dist-boot/c-Z5ZUQVUY.mjs +62 -0
- package/dist-boot/c-ZDZUKXF7.mjs +874 -0
- package/dist-boot/c-ZJYLGIC3.mjs +32 -0
- package/dist-boot/c-ZNA5CDMI.mjs +77 -0
- package/dist-boot/c-ZSO6DI3M.mjs +204 -0
- package/dist-boot/c-ZWUVHKMK.mjs +100 -0
- package/dist-boot/c-ZY4MESEW.mjs +832 -0
- package/dist-boot/c-ZZ5REI4L.mjs +329 -0
- package/dist-boot/cli.mjs +51 -0
- package/dist-boot/ext-anthropic-attribution.mjs +207 -0
- package/dist-boot/ext-pi-background-tasks.mjs +7234 -0
- package/dist-boot/ext-pi-subagents.mjs +37 -0
- package/dist-boot/ext-privateer-account.mjs +4426 -0
- package/dist-boot/ext-privateer-brand.mjs +5274 -0
- package/dist-boot/ext-privateer-codemode.mjs +37 -0
- package/dist-boot/ext-privateer-computer.mjs +626 -0
- package/dist-boot/ext-privateer-connect.mjs +1862 -0
- package/dist-boot/ext-privateer-context.mjs +323 -0
- package/dist-boot/ext-privateer-desktop.mjs +92 -0
- package/dist-boot/ext-privateer-final-audit.mjs +48 -0
- package/dist-boot/ext-privateer-fresh.mjs +81 -0
- package/dist-boot/ext-privateer-gate.mjs +5959 -0
- package/dist-boot/ext-privateer-hints.mjs +236 -0
- package/dist-boot/ext-privateer-media.mjs +2626 -0
- package/dist-boot/ext-privateer-models.mjs +3397 -0
- package/dist-boot/ext-privateer-posture.mjs +3006 -0
- package/dist-boot/ext-privateer-privacy.mjs +4578 -0
- package/dist-boot/ext-privateer-recovery.mjs +287 -0
- package/dist-boot/ext-privateer-speak.mjs +4754 -0
- package/dist-boot/ext-privateer-terminals.mjs +725 -0
- package/dist-boot/ext-privateer-tools.mjs +528 -0
- package/dist-boot/ext-privateer-truncation.mjs +74 -0
- package/dist-boot/ext-privateer-update.mjs +210 -0
- package/dist-boot/ext-privateer-vision.mjs +148 -0
- package/dist-boot/ext-privateer-web.mjs +543 -0
- package/dist-boot/ext-rpiv-ask-user-question.mjs +710 -0
- package/dist-boot/manifest.json +9 -0
- package/extensions/privateer-brand.ts +3 -1
- package/extensions/privateer-context.ts +4 -2
- package/extensions/privateer-final-audit.ts +17 -0
- package/extensions/privateer-gate.ts +55 -9
- package/extensions/privateer-recovery.ts +175 -0
- package/extensions/privateer-web.ts +4 -4
- package/package.json +3 -1
- package/patches/@earendil-works+pi-coding-agent+1.3.0.patch +199 -2
- package/patches/pi-background-tasks+2.6.10.patch +91 -7
- package/src/cli/chat.ts +7 -1
- package/src/config/moatManifest.json +2 -0
- package/src/config/whatsNew.json +4 -4
- package/src/context.ts +33 -5
- package/src/engine/finalAudit.ts +38 -0
- package/src/engine/stallWatchdog.ts +8 -1
- package/src/providers/account.ts +34 -3
- package/src/remote/attentionPush.ts +40 -0
- package/src/remote/liveTaskSession.ts +7 -1
- package/src/remote/relayClient.ts +38 -4
- package/src/remote/remoteBridge.ts +17 -0
- package/src/remote/transcriptSnapshot.ts +104 -0
|
@@ -0,0 +1,2897 @@
|
|
|
1
|
+
import{createRequire as __pvCR}from"node:module";import{fileURLToPath as __pvF}from"node:url";import{dirname as __pvD}from"node:path";const require=__pvCR(import.meta.url);const __pvUrl=(r)=>new URL(r,import.meta.url).href;const __pvFile=(r)=>__pvF(new URL(r,import.meta.url));
|
|
2
|
+
import {
|
|
3
|
+
ASN1Obj,
|
|
4
|
+
ByteStream,
|
|
5
|
+
HashAlgorithms,
|
|
6
|
+
KeyTypes,
|
|
7
|
+
Uint8ArrayToBase64,
|
|
8
|
+
Uint8ArrayToHex,
|
|
9
|
+
Uint8ArrayToString,
|
|
10
|
+
base64Decode,
|
|
11
|
+
base64ToUint8Array,
|
|
12
|
+
canonicalize,
|
|
13
|
+
hexToUint8Array,
|
|
14
|
+
importKey,
|
|
15
|
+
readBigInt64BE,
|
|
16
|
+
stringToUint8Array,
|
|
17
|
+
toDER,
|
|
18
|
+
uint8ArrayEqual,
|
|
19
|
+
verifySignature,
|
|
20
|
+
verifySignatureOverDigest
|
|
21
|
+
} from "./c-U4ITOXAN.mjs";
|
|
22
|
+
import {
|
|
23
|
+
__name
|
|
24
|
+
} from "./c-CN77DCGF.mjs";
|
|
25
|
+
|
|
26
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/interfaces.js
|
|
27
|
+
var SigstoreRoots;
|
|
28
|
+
(function(SigstoreRoots2) {
|
|
29
|
+
SigstoreRoots2["certificateAuthorities"] = "certificateAuthorities";
|
|
30
|
+
SigstoreRoots2["ctlogs"] = "ctlogs";
|
|
31
|
+
SigstoreRoots2["timestampAuthorities"] = "timestampAuthorities";
|
|
32
|
+
SigstoreRoots2["tlogs"] = "tlogs";
|
|
33
|
+
})(SigstoreRoots || (SigstoreRoots = {}));
|
|
34
|
+
var SUPPORTED_HASH_ALGORITHMS = {
|
|
35
|
+
"sha256": HashAlgorithms.SHA256,
|
|
36
|
+
"sha384": HashAlgorithms.SHA384,
|
|
37
|
+
"sha512": HashAlgorithms.SHA512,
|
|
38
|
+
"SHA2_256": HashAlgorithms.SHA256,
|
|
39
|
+
"SHA2_384": HashAlgorithms.SHA384,
|
|
40
|
+
"SHA2_512": HashAlgorithms.SHA512
|
|
41
|
+
};
|
|
42
|
+
function getHashAlgorithm(algorithm) {
|
|
43
|
+
const hashAlg = SUPPORTED_HASH_ALGORITHMS[algorithm];
|
|
44
|
+
if (!hashAlg) {
|
|
45
|
+
throw new Error(`Unsupported hash algorithm: ${algorithm}`);
|
|
46
|
+
}
|
|
47
|
+
return hashAlg;
|
|
48
|
+
}
|
|
49
|
+
__name(getHashAlgorithm, "getHashAlgorithm");
|
|
50
|
+
|
|
51
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/oid.js
|
|
52
|
+
var ECDSA_SIGNATURE_ALGOS = {
|
|
53
|
+
"1.2.840.10045.4.3.1": "sha224",
|
|
54
|
+
"1.2.840.10045.4.3.2": "sha256",
|
|
55
|
+
"1.2.840.10045.4.3.3": "sha384",
|
|
56
|
+
"1.2.840.10045.4.3.4": "sha512"
|
|
57
|
+
};
|
|
58
|
+
var RSA_SIGNATURE_ALGOS = {
|
|
59
|
+
"1.2.840.113549.1.1.11": "sha256",
|
|
60
|
+
// sha256WithRSAEncryption
|
|
61
|
+
"1.2.840.113549.1.1.12": "sha384",
|
|
62
|
+
// sha384WithRSAEncryption
|
|
63
|
+
"1.2.840.113549.1.1.13": "sha512",
|
|
64
|
+
// sha512WithRSAEncryption
|
|
65
|
+
"1.2.840.113549.1.1.5": "sha1"
|
|
66
|
+
// sha1WithRSAEncryption
|
|
67
|
+
};
|
|
68
|
+
var OID_RSASSA_PSS = "1.2.840.113549.1.1.10";
|
|
69
|
+
var SHA2_HASH_ALGOS = {
|
|
70
|
+
"2.16.840.1.101.3.4.2.1": "sha256",
|
|
71
|
+
"2.16.840.1.101.3.4.2.2": "sha384",
|
|
72
|
+
"2.16.840.1.101.3.4.2.3": "sha512"
|
|
73
|
+
};
|
|
74
|
+
var DEFAULT_HASH_ALGORITHM = "sha256";
|
|
75
|
+
var ECDSA_CURVE_NAMES = {
|
|
76
|
+
"1.2.840.10045.3.1.7": "secp256r1",
|
|
77
|
+
"1.3.132.0.34": "secp384r1",
|
|
78
|
+
"1.3.132.0.35": "secp521r1"
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/x509/sct.js
|
|
82
|
+
var SignedCertificateTimestamp = class _SignedCertificateTimestamp {
|
|
83
|
+
static {
|
|
84
|
+
__name(this, "SignedCertificateTimestamp");
|
|
85
|
+
}
|
|
86
|
+
constructor(options) {
|
|
87
|
+
this.version = options.version;
|
|
88
|
+
this.logID = options.logID;
|
|
89
|
+
this.timestamp = options.timestamp;
|
|
90
|
+
this.extensions = options.extensions;
|
|
91
|
+
this.hashAlgorithm = options.hashAlgorithm;
|
|
92
|
+
this.signatureAlgorithm = options.signatureAlgorithm;
|
|
93
|
+
this.signature = options.signature;
|
|
94
|
+
}
|
|
95
|
+
get datetime() {
|
|
96
|
+
return new Date(Number(readBigInt64BE(this.timestamp)));
|
|
97
|
+
}
|
|
98
|
+
// Returns the hash algorithm used to generate the SCT's signature.
|
|
99
|
+
// https://www.rfc-editor.org/rfc/rfc5246#section-7.4.1.4.1
|
|
100
|
+
get algorithm() {
|
|
101
|
+
switch (this.hashAlgorithm) {
|
|
102
|
+
/* istanbul ignore next */
|
|
103
|
+
case 0:
|
|
104
|
+
return "none";
|
|
105
|
+
/* istanbul ignore next */
|
|
106
|
+
case 1:
|
|
107
|
+
return "md5";
|
|
108
|
+
/* istanbul ignore next */
|
|
109
|
+
case 2:
|
|
110
|
+
return "sha1";
|
|
111
|
+
/* istanbul ignore next */
|
|
112
|
+
case 3:
|
|
113
|
+
return "sha224";
|
|
114
|
+
case 4:
|
|
115
|
+
return "sha256";
|
|
116
|
+
/* istanbul ignore next */
|
|
117
|
+
case 5:
|
|
118
|
+
return "sha384";
|
|
119
|
+
/* istanbul ignore next */
|
|
120
|
+
case 6:
|
|
121
|
+
return "sha512";
|
|
122
|
+
/* istanbul ignore next */
|
|
123
|
+
default:
|
|
124
|
+
return "unknown";
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async verify(preCert, key) {
|
|
128
|
+
const stream = new ByteStream();
|
|
129
|
+
stream.appendChar(this.version);
|
|
130
|
+
stream.appendChar(0);
|
|
131
|
+
stream.appendView(this.timestamp);
|
|
132
|
+
stream.appendUint16(1);
|
|
133
|
+
stream.appendView(preCert);
|
|
134
|
+
stream.appendUint16(this.extensions.byteLength);
|
|
135
|
+
if (this.extensions.byteLength > 0) {
|
|
136
|
+
stream.appendView(this.extensions);
|
|
137
|
+
}
|
|
138
|
+
return await verifySignature(key, stream.buffer, this.signature, this.algorithm);
|
|
139
|
+
}
|
|
140
|
+
// Parses a SignedCertificateTimestamp from a buffer. SCTs are encoded using
|
|
141
|
+
// TLS encoding which means the fields and lengths of most fields are
|
|
142
|
+
// specified as part of the SCT and TLS specs.
|
|
143
|
+
// https://www.rfc-editor.org/rfc/rfc6962#section-3.2
|
|
144
|
+
// https://www.rfc-editor.org/rfc/rfc5246#section-7.4.1.4.1
|
|
145
|
+
static parse(buf) {
|
|
146
|
+
const stream = new ByteStream(buf);
|
|
147
|
+
const version = stream.getUint8();
|
|
148
|
+
if (version !== 0) {
|
|
149
|
+
throw new Error(`Unsupported SCT version: ${version} (expected 0 for v1)`);
|
|
150
|
+
}
|
|
151
|
+
const logID = stream.getBlock(32);
|
|
152
|
+
const timestamp = stream.getBlock(8);
|
|
153
|
+
const extenstionLength = stream.getUint16();
|
|
154
|
+
const extensions = stream.getBlock(extenstionLength);
|
|
155
|
+
const hashAlgorithm = stream.getUint8();
|
|
156
|
+
const signatureAlgorithm = stream.getUint8();
|
|
157
|
+
const sigLength = stream.getUint16();
|
|
158
|
+
const signature = stream.getBlock(sigLength);
|
|
159
|
+
if (stream.position !== buf.length) {
|
|
160
|
+
throw new Error("SCT buffer length mismatch");
|
|
161
|
+
}
|
|
162
|
+
return new _SignedCertificateTimestamp({
|
|
163
|
+
version,
|
|
164
|
+
logID,
|
|
165
|
+
timestamp,
|
|
166
|
+
extensions,
|
|
167
|
+
hashAlgorithm,
|
|
168
|
+
signatureAlgorithm,
|
|
169
|
+
signature
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/x509/ext.js
|
|
175
|
+
var X509Extension = class {
|
|
176
|
+
static {
|
|
177
|
+
__name(this, "X509Extension");
|
|
178
|
+
}
|
|
179
|
+
constructor(asn1) {
|
|
180
|
+
this.root = asn1;
|
|
181
|
+
}
|
|
182
|
+
get oid() {
|
|
183
|
+
return this.root.subs[0].toOID();
|
|
184
|
+
}
|
|
185
|
+
get critical() {
|
|
186
|
+
return this.root.subs.length === 3 ? this.root.subs[1].toBoolean() : false;
|
|
187
|
+
}
|
|
188
|
+
get value() {
|
|
189
|
+
return this.extnValueObj.value;
|
|
190
|
+
}
|
|
191
|
+
get valueObj() {
|
|
192
|
+
return this.extnValueObj;
|
|
193
|
+
}
|
|
194
|
+
get extnValueObj() {
|
|
195
|
+
return this.root.subs[this.root.subs.length - 1];
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
var X509BasicConstraintsExtension = class extends X509Extension {
|
|
199
|
+
static {
|
|
200
|
+
__name(this, "X509BasicConstraintsExtension");
|
|
201
|
+
}
|
|
202
|
+
get isCA() {
|
|
203
|
+
return this.sequence.subs[0]?.toBoolean() ?? false;
|
|
204
|
+
}
|
|
205
|
+
get pathLenConstraint() {
|
|
206
|
+
return this.sequence.subs.length > 1 ? this.sequence.subs[1].toInteger() : void 0;
|
|
207
|
+
}
|
|
208
|
+
// The extnValue field contains a single sequence wrapping the isCA and
|
|
209
|
+
// pathLenConstraint.
|
|
210
|
+
get sequence() {
|
|
211
|
+
return this.extnValueObj.subs[0];
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
var X509KeyUsageExtension = class extends X509Extension {
|
|
215
|
+
static {
|
|
216
|
+
__name(this, "X509KeyUsageExtension");
|
|
217
|
+
}
|
|
218
|
+
get digitalSignature() {
|
|
219
|
+
return this.bitString[0] === 1;
|
|
220
|
+
}
|
|
221
|
+
get keyCertSign() {
|
|
222
|
+
return this.bitString[5] === 1;
|
|
223
|
+
}
|
|
224
|
+
get crlSign() {
|
|
225
|
+
return this.bitString[6] === 1;
|
|
226
|
+
}
|
|
227
|
+
// The extnValue field contains a single bit string which is a bit mask
|
|
228
|
+
// indicating which key usages are enabled.
|
|
229
|
+
get bitString() {
|
|
230
|
+
return this.extnValueObj.subs[0].toBitString();
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
var X509SubjectAlternativeNameExtension = class extends X509Extension {
|
|
234
|
+
static {
|
|
235
|
+
__name(this, "X509SubjectAlternativeNameExtension");
|
|
236
|
+
}
|
|
237
|
+
get rfc822Name() {
|
|
238
|
+
const rfc822Name = this.findGeneralName(1)?.value;
|
|
239
|
+
if (rfc822Name === void 0) {
|
|
240
|
+
return void 0;
|
|
241
|
+
} else {
|
|
242
|
+
return Uint8ArrayToString(rfc822Name);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
get uri() {
|
|
246
|
+
const uri = this.findGeneralName(6)?.value;
|
|
247
|
+
if (uri === void 0) {
|
|
248
|
+
return void 0;
|
|
249
|
+
} else {
|
|
250
|
+
return Uint8ArrayToString(uri);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// Retrieve the value of an otherName with the given OID.
|
|
254
|
+
otherName(oid) {
|
|
255
|
+
const otherName = this.findGeneralName(0);
|
|
256
|
+
if (otherName === void 0) {
|
|
257
|
+
return void 0;
|
|
258
|
+
}
|
|
259
|
+
const otherNameOID = otherName.subs[0].toOID();
|
|
260
|
+
if (otherNameOID !== oid) {
|
|
261
|
+
return void 0;
|
|
262
|
+
}
|
|
263
|
+
const otherNameValue = otherName.subs[1];
|
|
264
|
+
return Uint8ArrayToString(otherNameValue.subs[0].value);
|
|
265
|
+
}
|
|
266
|
+
findGeneralName(tag) {
|
|
267
|
+
return this.generalNames.find((gn) => gn.tag.isContextSpecific(tag));
|
|
268
|
+
}
|
|
269
|
+
// The extnValue field contains a sequence of GeneralNames.
|
|
270
|
+
get generalNames() {
|
|
271
|
+
return this.extnValueObj.subs[0].subs;
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
var X509AuthorityKeyIDExtension = class extends X509Extension {
|
|
275
|
+
static {
|
|
276
|
+
__name(this, "X509AuthorityKeyIDExtension");
|
|
277
|
+
}
|
|
278
|
+
get keyIdentifier() {
|
|
279
|
+
return this.findSequenceMember(0)?.value;
|
|
280
|
+
}
|
|
281
|
+
findSequenceMember(tag) {
|
|
282
|
+
return this.sequence.subs.find((el) => el.tag.isContextSpecific(tag));
|
|
283
|
+
}
|
|
284
|
+
// The extnValue field contains a single sequence wrapping the keyIdentifier
|
|
285
|
+
get sequence() {
|
|
286
|
+
return this.extnValueObj.subs[0];
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
var X509SubjectKeyIDExtension = class extends X509Extension {
|
|
290
|
+
static {
|
|
291
|
+
__name(this, "X509SubjectKeyIDExtension");
|
|
292
|
+
}
|
|
293
|
+
get keyIdentifier() {
|
|
294
|
+
return this.extnValueObj.subs[0].value;
|
|
295
|
+
}
|
|
296
|
+
};
|
|
297
|
+
var X509FulcioExtensionV1 = class extends X509Extension {
|
|
298
|
+
static {
|
|
299
|
+
__name(this, "X509FulcioExtensionV1");
|
|
300
|
+
}
|
|
301
|
+
get stringValue() {
|
|
302
|
+
return Uint8ArrayToString(this.extnValueObj.value);
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
var X509FulcioExtensionV2 = class extends X509Extension {
|
|
306
|
+
static {
|
|
307
|
+
__name(this, "X509FulcioExtensionV2");
|
|
308
|
+
}
|
|
309
|
+
get stringValue() {
|
|
310
|
+
return Uint8ArrayToString(this.extnValueObj.subs[0].value);
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
var X509FulcioIssuerV1 = class extends X509FulcioExtensionV1 {
|
|
314
|
+
static {
|
|
315
|
+
__name(this, "X509FulcioIssuerV1");
|
|
316
|
+
}
|
|
317
|
+
get issuer() {
|
|
318
|
+
return this.stringValue;
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
var X509GitHubWorkflowTriggerExtension = class extends X509FulcioExtensionV1 {
|
|
322
|
+
static {
|
|
323
|
+
__name(this, "X509GitHubWorkflowTriggerExtension");
|
|
324
|
+
}
|
|
325
|
+
get workflowTrigger() {
|
|
326
|
+
return this.stringValue;
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
var X509GitHubWorkflowSHAExtension = class extends X509FulcioExtensionV1 {
|
|
330
|
+
static {
|
|
331
|
+
__name(this, "X509GitHubWorkflowSHAExtension");
|
|
332
|
+
}
|
|
333
|
+
get workflowSHA() {
|
|
334
|
+
return this.stringValue;
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
var X509GitHubWorkflowNameExtension = class extends X509FulcioExtensionV1 {
|
|
338
|
+
static {
|
|
339
|
+
__name(this, "X509GitHubWorkflowNameExtension");
|
|
340
|
+
}
|
|
341
|
+
get workflowName() {
|
|
342
|
+
return this.stringValue;
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
var X509GitHubWorkflowRepositoryExtension = class extends X509FulcioExtensionV1 {
|
|
346
|
+
static {
|
|
347
|
+
__name(this, "X509GitHubWorkflowRepositoryExtension");
|
|
348
|
+
}
|
|
349
|
+
get workflowRepository() {
|
|
350
|
+
return this.stringValue;
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
var X509GitHubWorkflowRefExtension = class extends X509FulcioExtensionV1 {
|
|
354
|
+
static {
|
|
355
|
+
__name(this, "X509GitHubWorkflowRefExtension");
|
|
356
|
+
}
|
|
357
|
+
get workflowRef() {
|
|
358
|
+
return this.stringValue;
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
var X509FulcioIssuerV2 = class extends X509FulcioExtensionV2 {
|
|
362
|
+
static {
|
|
363
|
+
__name(this, "X509FulcioIssuerV2");
|
|
364
|
+
}
|
|
365
|
+
get issuer() {
|
|
366
|
+
return this.stringValue;
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
var X509BuildSignerURIExtension = class extends X509FulcioExtensionV2 {
|
|
370
|
+
static {
|
|
371
|
+
__name(this, "X509BuildSignerURIExtension");
|
|
372
|
+
}
|
|
373
|
+
get buildSignerURI() {
|
|
374
|
+
return this.stringValue;
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
var X509BuildSignerDigestExtension = class extends X509FulcioExtensionV2 {
|
|
378
|
+
static {
|
|
379
|
+
__name(this, "X509BuildSignerDigestExtension");
|
|
380
|
+
}
|
|
381
|
+
get buildSignerDigest() {
|
|
382
|
+
return this.stringValue;
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
var X509RunnerEnvironmentExtension = class extends X509FulcioExtensionV2 {
|
|
386
|
+
static {
|
|
387
|
+
__name(this, "X509RunnerEnvironmentExtension");
|
|
388
|
+
}
|
|
389
|
+
get runnerEnvironment() {
|
|
390
|
+
return this.stringValue;
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
var X509SourceRepositoryURIExtension = class extends X509FulcioExtensionV2 {
|
|
394
|
+
static {
|
|
395
|
+
__name(this, "X509SourceRepositoryURIExtension");
|
|
396
|
+
}
|
|
397
|
+
get sourceRepositoryURI() {
|
|
398
|
+
return this.stringValue;
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
var X509SourceRepositoryDigestExtension = class extends X509FulcioExtensionV2 {
|
|
402
|
+
static {
|
|
403
|
+
__name(this, "X509SourceRepositoryDigestExtension");
|
|
404
|
+
}
|
|
405
|
+
get sourceRepositoryDigest() {
|
|
406
|
+
return this.stringValue;
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
var X509SourceRepositoryRefExtension = class extends X509FulcioExtensionV2 {
|
|
410
|
+
static {
|
|
411
|
+
__name(this, "X509SourceRepositoryRefExtension");
|
|
412
|
+
}
|
|
413
|
+
get sourceRepositoryRef() {
|
|
414
|
+
return this.stringValue;
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
var X509SourceRepositoryIdentifierExtension = class extends X509FulcioExtensionV2 {
|
|
418
|
+
static {
|
|
419
|
+
__name(this, "X509SourceRepositoryIdentifierExtension");
|
|
420
|
+
}
|
|
421
|
+
get sourceRepositoryIdentifier() {
|
|
422
|
+
return this.stringValue;
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
var X509SourceRepositoryOwnerURIExtension = class extends X509FulcioExtensionV2 {
|
|
426
|
+
static {
|
|
427
|
+
__name(this, "X509SourceRepositoryOwnerURIExtension");
|
|
428
|
+
}
|
|
429
|
+
get sourceRepositoryOwnerURI() {
|
|
430
|
+
return this.stringValue;
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
var X509SourceRepositoryOwnerIdentifierExtension = class extends X509FulcioExtensionV2 {
|
|
434
|
+
static {
|
|
435
|
+
__name(this, "X509SourceRepositoryOwnerIdentifierExtension");
|
|
436
|
+
}
|
|
437
|
+
get sourceRepositoryOwnerIdentifier() {
|
|
438
|
+
return this.stringValue;
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
var X509BuildConfigURIExtension = class extends X509FulcioExtensionV2 {
|
|
442
|
+
static {
|
|
443
|
+
__name(this, "X509BuildConfigURIExtension");
|
|
444
|
+
}
|
|
445
|
+
get buildConfigURI() {
|
|
446
|
+
return this.stringValue;
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
var X509BuildConfigDigestExtension = class extends X509FulcioExtensionV2 {
|
|
450
|
+
static {
|
|
451
|
+
__name(this, "X509BuildConfigDigestExtension");
|
|
452
|
+
}
|
|
453
|
+
get buildConfigDigest() {
|
|
454
|
+
return this.stringValue;
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
var X509BuildTriggerExtension = class extends X509FulcioExtensionV2 {
|
|
458
|
+
static {
|
|
459
|
+
__name(this, "X509BuildTriggerExtension");
|
|
460
|
+
}
|
|
461
|
+
get buildTrigger() {
|
|
462
|
+
return this.stringValue;
|
|
463
|
+
}
|
|
464
|
+
};
|
|
465
|
+
var X509RunInvocationURIExtension = class extends X509FulcioExtensionV2 {
|
|
466
|
+
static {
|
|
467
|
+
__name(this, "X509RunInvocationURIExtension");
|
|
468
|
+
}
|
|
469
|
+
get runInvocationURI() {
|
|
470
|
+
return this.stringValue;
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
var X509SourceRepositoryVisibilityExtension = class extends X509FulcioExtensionV2 {
|
|
474
|
+
static {
|
|
475
|
+
__name(this, "X509SourceRepositoryVisibilityExtension");
|
|
476
|
+
}
|
|
477
|
+
get sourceRepositoryVisibility() {
|
|
478
|
+
return this.stringValue;
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
var X509SCTExtension = class extends X509Extension {
|
|
482
|
+
static {
|
|
483
|
+
__name(this, "X509SCTExtension");
|
|
484
|
+
}
|
|
485
|
+
constructor(asn1) {
|
|
486
|
+
super(asn1);
|
|
487
|
+
}
|
|
488
|
+
get signedCertificateTimestamps() {
|
|
489
|
+
const buf = this.extnValueObj.subs[0].value;
|
|
490
|
+
const stream = new ByteStream(buf);
|
|
491
|
+
const end = stream.getUint16() + 2;
|
|
492
|
+
const sctList = [];
|
|
493
|
+
while (stream.position < end) {
|
|
494
|
+
const sctLength = stream.getUint16();
|
|
495
|
+
const sct = stream.getBlock(sctLength);
|
|
496
|
+
sctList.push(SignedCertificateTimestamp.parse(sct));
|
|
497
|
+
}
|
|
498
|
+
if (stream.position !== end) {
|
|
499
|
+
throw new Error("SCT list length does not match actual length");
|
|
500
|
+
}
|
|
501
|
+
return sctList;
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/x509/cert.js
|
|
506
|
+
var EXTENSION_OID_SUBJECT_KEY_ID = "2.5.29.14";
|
|
507
|
+
var EXTENSION_OID_KEY_USAGE = "2.5.29.15";
|
|
508
|
+
var EXTENSION_OID_SUBJECT_ALT_NAME = "2.5.29.17";
|
|
509
|
+
var EXTENSION_OID_BASIC_CONSTRAINTS = "2.5.29.19";
|
|
510
|
+
var EXTENSION_OID_AUTHORITY_KEY_ID = "2.5.29.35";
|
|
511
|
+
var EXTENSION_OID_SCT = "1.3.6.1.4.1.11129.2.4.2";
|
|
512
|
+
var DN_OID_COMMON_NAME = "2.5.4.3";
|
|
513
|
+
var DN_OID_COUNTRY = "2.5.4.6";
|
|
514
|
+
var DN_OID_LOCALITY = "2.5.4.7";
|
|
515
|
+
var DN_OID_STATE = "2.5.4.8";
|
|
516
|
+
var DN_OID_ORGANIZATION = "2.5.4.10";
|
|
517
|
+
var DN_OID_ORGANIZATIONAL_UNIT = "2.5.4.11";
|
|
518
|
+
var DN_OID_TO_NAME = {
|
|
519
|
+
[DN_OID_COMMON_NAME]: "CN",
|
|
520
|
+
[DN_OID_COUNTRY]: "C",
|
|
521
|
+
[DN_OID_LOCALITY]: "L",
|
|
522
|
+
[DN_OID_STATE]: "ST",
|
|
523
|
+
[DN_OID_ORGANIZATION]: "O",
|
|
524
|
+
[DN_OID_ORGANIZATIONAL_UNIT]: "OU"
|
|
525
|
+
};
|
|
526
|
+
var EXTENSION_OID_FULCIO_ISSUER_V1 = "1.3.6.1.4.1.57264.1.1";
|
|
527
|
+
var EXTENSION_OID_GITHUB_WORKFLOW_TRIGGER = "1.3.6.1.4.1.57264.1.2";
|
|
528
|
+
var EXTENSION_OID_GITHUB_WORKFLOW_SHA = "1.3.6.1.4.1.57264.1.3";
|
|
529
|
+
var EXTENSION_OID_GITHUB_WORKFLOW_NAME = "1.3.6.1.4.1.57264.1.4";
|
|
530
|
+
var EXTENSION_OID_GITHUB_WORKFLOW_REPOSITORY = "1.3.6.1.4.1.57264.1.5";
|
|
531
|
+
var EXTENSION_OID_GITHUB_WORKFLOW_REF = "1.3.6.1.4.1.57264.1.6";
|
|
532
|
+
var EXTENSION_OID_OTHERNAME = "1.3.6.1.4.1.57264.1.7";
|
|
533
|
+
var EXTENSION_OID_FULCIO_ISSUER_V2 = "1.3.6.1.4.1.57264.1.8";
|
|
534
|
+
var EXTENSION_OID_BUILD_SIGNER_URI = "1.3.6.1.4.1.57264.1.9";
|
|
535
|
+
var EXTENSION_OID_BUILD_SIGNER_DIGEST = "1.3.6.1.4.1.57264.1.10";
|
|
536
|
+
var EXTENSION_OID_RUNNER_ENVIRONMENT = "1.3.6.1.4.1.57264.1.11";
|
|
537
|
+
var EXTENSION_OID_SOURCE_REPOSITORY_URI = "1.3.6.1.4.1.57264.1.12";
|
|
538
|
+
var EXTENSION_OID_SOURCE_REPOSITORY_DIGEST = "1.3.6.1.4.1.57264.1.13";
|
|
539
|
+
var EXTENSION_OID_SOURCE_REPOSITORY_REF = "1.3.6.1.4.1.57264.1.14";
|
|
540
|
+
var EXTENSION_OID_SOURCE_REPOSITORY_IDENTIFIER = "1.3.6.1.4.1.57264.1.15";
|
|
541
|
+
var EXTENSION_OID_SOURCE_REPOSITORY_OWNER_URI = "1.3.6.1.4.1.57264.1.16";
|
|
542
|
+
var EXTENSION_OID_SOURCE_REPOSITORY_OWNER_IDENTIFIER = "1.3.6.1.4.1.57264.1.17";
|
|
543
|
+
var EXTENSION_OID_BUILD_CONFIG_URI = "1.3.6.1.4.1.57264.1.18";
|
|
544
|
+
var EXTENSION_OID_BUILD_CONFIG_DIGEST = "1.3.6.1.4.1.57264.1.19";
|
|
545
|
+
var EXTENSION_OID_BUILD_TRIGGER = "1.3.6.1.4.1.57264.1.20";
|
|
546
|
+
var EXTENSION_OID_RUN_INVOCATION_URI = "1.3.6.1.4.1.57264.1.21";
|
|
547
|
+
var EXTENSION_OID_SOURCE_REPOSITORY_VISIBILITY = "1.3.6.1.4.1.57264.1.22";
|
|
548
|
+
var X509Certificate = class _X509Certificate {
|
|
549
|
+
static {
|
|
550
|
+
__name(this, "X509Certificate");
|
|
551
|
+
}
|
|
552
|
+
constructor(asn1) {
|
|
553
|
+
this.root = asn1;
|
|
554
|
+
}
|
|
555
|
+
static parse(cert) {
|
|
556
|
+
const der = typeof cert === "string" ? toDER(cert) : cert;
|
|
557
|
+
const asn1 = ASN1Obj.parseBuffer(der);
|
|
558
|
+
return new _X509Certificate(asn1);
|
|
559
|
+
}
|
|
560
|
+
get tbsCertificate() {
|
|
561
|
+
return this.tbsCertificateObj;
|
|
562
|
+
}
|
|
563
|
+
get version() {
|
|
564
|
+
const ver = this.versionObj.subs[0].toInteger();
|
|
565
|
+
return `v${(ver + BigInt(1)).toString()}`;
|
|
566
|
+
}
|
|
567
|
+
get serialNumber() {
|
|
568
|
+
return this.serialNumberObj.value;
|
|
569
|
+
}
|
|
570
|
+
get notBefore() {
|
|
571
|
+
return this.validityObj.subs[0].toDate();
|
|
572
|
+
}
|
|
573
|
+
get notAfter() {
|
|
574
|
+
return this.validityObj.subs[1].toDate();
|
|
575
|
+
}
|
|
576
|
+
get issuer() {
|
|
577
|
+
return this.issuerObj.value;
|
|
578
|
+
}
|
|
579
|
+
get subject() {
|
|
580
|
+
return this.subjectObj.value;
|
|
581
|
+
}
|
|
582
|
+
/**
|
|
583
|
+
* Returns the issuer distinguished name as a Map of attribute names to values.
|
|
584
|
+
* Common attributes: CN (Common Name), O (Organization), L (Locality),
|
|
585
|
+
* ST (State), C (Country), OU (Organizational Unit)
|
|
586
|
+
*/
|
|
587
|
+
get issuerDN() {
|
|
588
|
+
return this.parseDistinguishedName(this.issuerObj);
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Returns the subject distinguished name as a Map of attribute names to values.
|
|
592
|
+
* Common attributes: CN (Common Name), O (Organization), L (Locality),
|
|
593
|
+
* ST (State), C (Country), OU (Organizational Unit)
|
|
594
|
+
*/
|
|
595
|
+
get subjectDN() {
|
|
596
|
+
return this.parseDistinguishedName(this.subjectObj);
|
|
597
|
+
}
|
|
598
|
+
get publicKey() {
|
|
599
|
+
return this.subjectPublicKeyInfoObj.toDER();
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Import the public key with a specific hash algorithm and signature scheme for RSA keys.
|
|
603
|
+
* For ECDSA keys, both parameters are ignored.
|
|
604
|
+
* @param hashAlg - Hash algorithm (e.g., "sha384") for RSA keys
|
|
605
|
+
* @param usePss - If true, import as RSA-PSS key; if false, import as PKCS#1 v1.5
|
|
606
|
+
*/
|
|
607
|
+
async getPublicKeyObj(hashAlg, usePss) {
|
|
608
|
+
const publicKey = this.subjectPublicKeyInfoObj.toDER();
|
|
609
|
+
const spki = ASN1Obj.parseBuffer(publicKey);
|
|
610
|
+
const algorithmOID = spki.subs[0].subs[0].toOID();
|
|
611
|
+
const isRsaKey = algorithmOID === "1.2.840.113549.1.1.1";
|
|
612
|
+
const isRsaPssKey = algorithmOID === OID_RSASSA_PSS;
|
|
613
|
+
if (isRsaPssKey) {
|
|
614
|
+
throw new Error("RSA-PSS public keys (id-RSASSA-PSS OID) are not supported by WebCrypto. Only certificates with standard RSA keys (rsaEncryption OID) signed using RSA-PSS are supported.");
|
|
615
|
+
}
|
|
616
|
+
if (isRsaKey) {
|
|
617
|
+
const hash = hashAlg || DEFAULT_HASH_ALGORITHM;
|
|
618
|
+
const scheme = usePss ? hash : `PKCS1_${hash}`;
|
|
619
|
+
return importKey(KeyTypes.RSA, scheme, Uint8ArrayToBase64(publicKey));
|
|
620
|
+
} else {
|
|
621
|
+
const curveOID = spki.subs[0].subs[1]?.toOID();
|
|
622
|
+
const curve = ECDSA_CURVE_NAMES[curveOID];
|
|
623
|
+
if (!curve) {
|
|
624
|
+
throw new Error(`Unknown ECDSA curve OID: ${curveOID}`);
|
|
625
|
+
}
|
|
626
|
+
return importKey(KeyTypes.Ecdsa, curve, Uint8ArrayToBase64(publicKey));
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
get publicKeyObj() {
|
|
630
|
+
return this.getPublicKeyObj();
|
|
631
|
+
}
|
|
632
|
+
get signatureAlgorithm() {
|
|
633
|
+
const oid = this.signatureAlgorithmObj.subs[0].toOID();
|
|
634
|
+
return ECDSA_SIGNATURE_ALGOS[oid] || RSA_SIGNATURE_ALGOS[oid] || this.parseRsaPssHashAlgorithm();
|
|
635
|
+
}
|
|
636
|
+
get signatureAlgorithmOid() {
|
|
637
|
+
return this.signatureAlgorithmObj.subs[0].toOID();
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Parse hash algorithm from RSA-PSS signature algorithm parameters.
|
|
641
|
+
* RSA-PSS parameters are: SEQUENCE { hashAlgorithm, maskGenAlgorithm, saltLength, trailerField }
|
|
642
|
+
*/
|
|
643
|
+
parseRsaPssHashAlgorithm() {
|
|
644
|
+
const sigAlgOid = this.signatureAlgorithmObj.subs[0].toOID();
|
|
645
|
+
if (sigAlgOid !== OID_RSASSA_PSS) {
|
|
646
|
+
return "";
|
|
647
|
+
}
|
|
648
|
+
const params = this.signatureAlgorithmObj.subs[1];
|
|
649
|
+
if (!params || params.subs.length === 0) {
|
|
650
|
+
return DEFAULT_HASH_ALGORITHM;
|
|
651
|
+
}
|
|
652
|
+
const hashAlgWrapper = params.subs[0];
|
|
653
|
+
if (hashAlgWrapper && hashAlgWrapper.subs.length > 0) {
|
|
654
|
+
const hashAlgSeq = hashAlgWrapper.subs[0];
|
|
655
|
+
if (hashAlgSeq && hashAlgSeq.subs.length > 0) {
|
|
656
|
+
const hashOid = hashAlgSeq.subs[0].toOID();
|
|
657
|
+
return SHA2_HASH_ALGOS[hashOid] || DEFAULT_HASH_ALGORITHM;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
return DEFAULT_HASH_ALGORITHM;
|
|
661
|
+
}
|
|
662
|
+
get signatureValue() {
|
|
663
|
+
return this.signatureValueObj.value.subarray(1);
|
|
664
|
+
}
|
|
665
|
+
get subjectAltName() {
|
|
666
|
+
const ext = this.extSubjectAltName;
|
|
667
|
+
return ext?.uri || ext?.rfc822Name;
|
|
668
|
+
}
|
|
669
|
+
get extensions() {
|
|
670
|
+
const extSeq = this.extensionsObj?.subs[0];
|
|
671
|
+
return extSeq?.subs || /* istanbul ignore next */
|
|
672
|
+
[];
|
|
673
|
+
}
|
|
674
|
+
get extKeyUsage() {
|
|
675
|
+
const ext = this.findExtension(EXTENSION_OID_KEY_USAGE);
|
|
676
|
+
return ext ? new X509KeyUsageExtension(ext) : void 0;
|
|
677
|
+
}
|
|
678
|
+
get extBasicConstraints() {
|
|
679
|
+
const ext = this.findExtension(EXTENSION_OID_BASIC_CONSTRAINTS);
|
|
680
|
+
return ext ? new X509BasicConstraintsExtension(ext) : void 0;
|
|
681
|
+
}
|
|
682
|
+
get extSubjectAltName() {
|
|
683
|
+
const ext = this.findExtension(EXTENSION_OID_SUBJECT_ALT_NAME);
|
|
684
|
+
return ext ? new X509SubjectAlternativeNameExtension(ext) : void 0;
|
|
685
|
+
}
|
|
686
|
+
get extAuthorityKeyID() {
|
|
687
|
+
const ext = this.findExtension(EXTENSION_OID_AUTHORITY_KEY_ID);
|
|
688
|
+
return ext ? new X509AuthorityKeyIDExtension(ext) : void 0;
|
|
689
|
+
}
|
|
690
|
+
get extSubjectKeyID() {
|
|
691
|
+
const ext = this.findExtension(EXTENSION_OID_SUBJECT_KEY_ID);
|
|
692
|
+
return ext ? new X509SubjectKeyIDExtension(ext) : (
|
|
693
|
+
/* istanbul ignore next */
|
|
694
|
+
void 0
|
|
695
|
+
);
|
|
696
|
+
}
|
|
697
|
+
get extSCT() {
|
|
698
|
+
const ext = this.findExtension(EXTENSION_OID_SCT);
|
|
699
|
+
return ext ? new X509SCTExtension(ext) : void 0;
|
|
700
|
+
}
|
|
701
|
+
get extFulcioIssuerV1() {
|
|
702
|
+
const ext = this.findExtension(EXTENSION_OID_FULCIO_ISSUER_V1);
|
|
703
|
+
return ext ? new X509FulcioIssuerV1(ext) : void 0;
|
|
704
|
+
}
|
|
705
|
+
get extFulcioIssuerV2() {
|
|
706
|
+
const ext = this.findExtension(EXTENSION_OID_FULCIO_ISSUER_V2);
|
|
707
|
+
return ext ? new X509FulcioIssuerV2(ext) : void 0;
|
|
708
|
+
}
|
|
709
|
+
get extGitHubWorkflowTrigger() {
|
|
710
|
+
const ext = this.findExtension(EXTENSION_OID_GITHUB_WORKFLOW_TRIGGER);
|
|
711
|
+
return ext ? new X509GitHubWorkflowTriggerExtension(ext) : void 0;
|
|
712
|
+
}
|
|
713
|
+
get extGitHubWorkflowSHA() {
|
|
714
|
+
const ext = this.findExtension(EXTENSION_OID_GITHUB_WORKFLOW_SHA);
|
|
715
|
+
return ext ? new X509GitHubWorkflowSHAExtension(ext) : void 0;
|
|
716
|
+
}
|
|
717
|
+
get extGitHubWorkflowName() {
|
|
718
|
+
const ext = this.findExtension(EXTENSION_OID_GITHUB_WORKFLOW_NAME);
|
|
719
|
+
return ext ? new X509GitHubWorkflowNameExtension(ext) : void 0;
|
|
720
|
+
}
|
|
721
|
+
get extGitHubWorkflowRepository() {
|
|
722
|
+
const ext = this.findExtension(EXTENSION_OID_GITHUB_WORKFLOW_REPOSITORY);
|
|
723
|
+
return ext ? new X509GitHubWorkflowRepositoryExtension(ext) : void 0;
|
|
724
|
+
}
|
|
725
|
+
get extGitHubWorkflowRef() {
|
|
726
|
+
const ext = this.findExtension(EXTENSION_OID_GITHUB_WORKFLOW_REF);
|
|
727
|
+
return ext ? new X509GitHubWorkflowRefExtension(ext) : void 0;
|
|
728
|
+
}
|
|
729
|
+
get extBuildSignerURI() {
|
|
730
|
+
const ext = this.findExtension(EXTENSION_OID_BUILD_SIGNER_URI);
|
|
731
|
+
return ext ? new X509BuildSignerURIExtension(ext) : void 0;
|
|
732
|
+
}
|
|
733
|
+
get extBuildSignerDigest() {
|
|
734
|
+
const ext = this.findExtension(EXTENSION_OID_BUILD_SIGNER_DIGEST);
|
|
735
|
+
return ext ? new X509BuildSignerDigestExtension(ext) : void 0;
|
|
736
|
+
}
|
|
737
|
+
get extRunnerEnvironment() {
|
|
738
|
+
const ext = this.findExtension(EXTENSION_OID_RUNNER_ENVIRONMENT);
|
|
739
|
+
return ext ? new X509RunnerEnvironmentExtension(ext) : void 0;
|
|
740
|
+
}
|
|
741
|
+
get extSourceRepositoryURI() {
|
|
742
|
+
const ext = this.findExtension(EXTENSION_OID_SOURCE_REPOSITORY_URI);
|
|
743
|
+
return ext ? new X509SourceRepositoryURIExtension(ext) : void 0;
|
|
744
|
+
}
|
|
745
|
+
get extSourceRepositoryDigest() {
|
|
746
|
+
const ext = this.findExtension(EXTENSION_OID_SOURCE_REPOSITORY_DIGEST);
|
|
747
|
+
return ext ? new X509SourceRepositoryDigestExtension(ext) : void 0;
|
|
748
|
+
}
|
|
749
|
+
get extSourceRepositoryRef() {
|
|
750
|
+
const ext = this.findExtension(EXTENSION_OID_SOURCE_REPOSITORY_REF);
|
|
751
|
+
return ext ? new X509SourceRepositoryRefExtension(ext) : void 0;
|
|
752
|
+
}
|
|
753
|
+
get extSourceRepositoryIdentifier() {
|
|
754
|
+
const ext = this.findExtension(EXTENSION_OID_SOURCE_REPOSITORY_IDENTIFIER);
|
|
755
|
+
return ext ? new X509SourceRepositoryIdentifierExtension(ext) : void 0;
|
|
756
|
+
}
|
|
757
|
+
get extSourceRepositoryOwnerURI() {
|
|
758
|
+
const ext = this.findExtension(EXTENSION_OID_SOURCE_REPOSITORY_OWNER_URI);
|
|
759
|
+
return ext ? new X509SourceRepositoryOwnerURIExtension(ext) : void 0;
|
|
760
|
+
}
|
|
761
|
+
get extSourceRepositoryOwnerIdentifier() {
|
|
762
|
+
const ext = this.findExtension(EXTENSION_OID_SOURCE_REPOSITORY_OWNER_IDENTIFIER);
|
|
763
|
+
return ext ? new X509SourceRepositoryOwnerIdentifierExtension(ext) : void 0;
|
|
764
|
+
}
|
|
765
|
+
get extBuildConfigURI() {
|
|
766
|
+
const ext = this.findExtension(EXTENSION_OID_BUILD_CONFIG_URI);
|
|
767
|
+
return ext ? new X509BuildConfigURIExtension(ext) : void 0;
|
|
768
|
+
}
|
|
769
|
+
get extBuildConfigDigest() {
|
|
770
|
+
const ext = this.findExtension(EXTENSION_OID_BUILD_CONFIG_DIGEST);
|
|
771
|
+
return ext ? new X509BuildConfigDigestExtension(ext) : void 0;
|
|
772
|
+
}
|
|
773
|
+
get extBuildTrigger() {
|
|
774
|
+
const ext = this.findExtension(EXTENSION_OID_BUILD_TRIGGER);
|
|
775
|
+
return ext ? new X509BuildTriggerExtension(ext) : void 0;
|
|
776
|
+
}
|
|
777
|
+
get extRunInvocationURI() {
|
|
778
|
+
const ext = this.findExtension(EXTENSION_OID_RUN_INVOCATION_URI);
|
|
779
|
+
return ext ? new X509RunInvocationURIExtension(ext) : void 0;
|
|
780
|
+
}
|
|
781
|
+
get extSourceRepositoryVisibility() {
|
|
782
|
+
const ext = this.findExtension(EXTENSION_OID_SOURCE_REPOSITORY_VISIBILITY);
|
|
783
|
+
return ext ? new X509SourceRepositoryVisibilityExtension(ext) : void 0;
|
|
784
|
+
}
|
|
785
|
+
get isCA() {
|
|
786
|
+
const ca = this.extBasicConstraints?.isCA || false;
|
|
787
|
+
if (this.extKeyUsage) {
|
|
788
|
+
return ca && this.extKeyUsage.keyCertSign;
|
|
789
|
+
}
|
|
790
|
+
return ca;
|
|
791
|
+
}
|
|
792
|
+
extension(oid) {
|
|
793
|
+
const ext = this.findExtension(oid);
|
|
794
|
+
return ext ? new X509Extension(ext) : void 0;
|
|
795
|
+
}
|
|
796
|
+
async verify(issuerCertificate) {
|
|
797
|
+
const sigAlgOID = this.signatureAlgorithmOid;
|
|
798
|
+
const isRsaPss = sigAlgOID === OID_RSASSA_PSS;
|
|
799
|
+
const hashAlg = isRsaPss ? this.parseRsaPssHashAlgorithm() : RSA_SIGNATURE_ALGOS[sigAlgOID] || ECDSA_SIGNATURE_ALGOS[sigAlgOID];
|
|
800
|
+
const publicKeyObj = issuerCertificate ? await issuerCertificate.getPublicKeyObj(hashAlg, isRsaPss) : await this.getPublicKeyObj(hashAlg, isRsaPss);
|
|
801
|
+
return await verifySignature(publicKeyObj, this.tbsCertificate.toDER(), this.signatureValue, this.signatureAlgorithm);
|
|
802
|
+
}
|
|
803
|
+
validForDate(date) {
|
|
804
|
+
return this.notBefore <= date && date <= this.notAfter;
|
|
805
|
+
}
|
|
806
|
+
equals(other) {
|
|
807
|
+
return uint8ArrayEqual(this.root.toDER(), other.root.toDER());
|
|
808
|
+
}
|
|
809
|
+
// Creates a copy of the certificate with a new buffer
|
|
810
|
+
clone() {
|
|
811
|
+
const der = this.root.toDER();
|
|
812
|
+
const clone = new Uint8Array(der);
|
|
813
|
+
return _X509Certificate.parse(clone);
|
|
814
|
+
}
|
|
815
|
+
findExtension(oid) {
|
|
816
|
+
return this.extensions.find((ext) => ext.subs[0].toOID() === oid);
|
|
817
|
+
}
|
|
818
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
819
|
+
// The following properties use the documented x509 structure to locate the
|
|
820
|
+
// desired ASN.1 object
|
|
821
|
+
// https://www.rfc-editor.org/rfc/rfc5280#section-4.1
|
|
822
|
+
// https://www.rfc-editor.org/rfc/rfc5280#section-4.1.1.1
|
|
823
|
+
get tbsCertificateObj() {
|
|
824
|
+
return this.root.subs[0];
|
|
825
|
+
}
|
|
826
|
+
// https://www.rfc-editor.org/rfc/rfc5280#section-4.1.1.2
|
|
827
|
+
get signatureAlgorithmObj() {
|
|
828
|
+
return this.root.subs[1];
|
|
829
|
+
}
|
|
830
|
+
// https://www.rfc-editor.org/rfc/rfc5280#section-4.1.1.3
|
|
831
|
+
get signatureValueObj() {
|
|
832
|
+
return this.root.subs[2];
|
|
833
|
+
}
|
|
834
|
+
// https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.1
|
|
835
|
+
get versionObj() {
|
|
836
|
+
return this.tbsCertificateObj.subs[0];
|
|
837
|
+
}
|
|
838
|
+
// https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.2
|
|
839
|
+
get serialNumberObj() {
|
|
840
|
+
return this.tbsCertificateObj.subs[1];
|
|
841
|
+
}
|
|
842
|
+
// https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.4
|
|
843
|
+
get issuerObj() {
|
|
844
|
+
return this.tbsCertificateObj.subs[3];
|
|
845
|
+
}
|
|
846
|
+
// https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.5
|
|
847
|
+
get validityObj() {
|
|
848
|
+
return this.tbsCertificateObj.subs[4];
|
|
849
|
+
}
|
|
850
|
+
// https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.6
|
|
851
|
+
get subjectObj() {
|
|
852
|
+
return this.tbsCertificateObj.subs[5];
|
|
853
|
+
}
|
|
854
|
+
// https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.7
|
|
855
|
+
get subjectPublicKeyInfoObj() {
|
|
856
|
+
return this.tbsCertificateObj.subs[6];
|
|
857
|
+
}
|
|
858
|
+
// Extensions can't be located by index because their position varies. Instead,
|
|
859
|
+
// we need to find the extensions context specific tag
|
|
860
|
+
// https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.9
|
|
861
|
+
get extensionsObj() {
|
|
862
|
+
return this.tbsCertificateObj.subs.find((sub) => sub.tag.isContextSpecific(3));
|
|
863
|
+
}
|
|
864
|
+
// Parse a Distinguished Name (issuer or subject) ASN1Obj into a Map
|
|
865
|
+
// DN structure: SEQUENCE of SET of SEQUENCE (AttributeTypeAndValue)
|
|
866
|
+
// Each AttributeTypeAndValue is [OID, value]
|
|
867
|
+
parseDistinguishedName(dnObj) {
|
|
868
|
+
const result = /* @__PURE__ */ new Map();
|
|
869
|
+
for (const rdn of dnObj.subs) {
|
|
870
|
+
for (const atv of rdn.subs) {
|
|
871
|
+
if (atv.subs.length >= 2) {
|
|
872
|
+
const oidObj = atv.subs[0];
|
|
873
|
+
const valueObj = atv.subs[1];
|
|
874
|
+
if (oidObj.tag.isOID()) {
|
|
875
|
+
const oid = oidObj.toOID();
|
|
876
|
+
const attrName = DN_OID_TO_NAME[oid];
|
|
877
|
+
if (attrName) {
|
|
878
|
+
const value = new TextDecoder().decode(valueObj.value);
|
|
879
|
+
result.set(attrName, value);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
return result;
|
|
886
|
+
}
|
|
887
|
+
};
|
|
888
|
+
|
|
889
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/x509/chain.js
|
|
890
|
+
var CertificateChainVerifier = class {
|
|
891
|
+
static {
|
|
892
|
+
__name(this, "CertificateChainVerifier");
|
|
893
|
+
}
|
|
894
|
+
constructor(opts) {
|
|
895
|
+
this.untrustedCert = opts.untrustedCert;
|
|
896
|
+
this.trustedCerts = opts.trustedCerts;
|
|
897
|
+
this.localCerts = dedupeCertificates([
|
|
898
|
+
...opts.trustedCerts,
|
|
899
|
+
opts.untrustedCert
|
|
900
|
+
]);
|
|
901
|
+
this.timestamp = opts.timestamp;
|
|
902
|
+
}
|
|
903
|
+
async verify() {
|
|
904
|
+
const certificatePath = await this.sort();
|
|
905
|
+
this.checkPath(certificatePath);
|
|
906
|
+
const validForDate = certificatePath.every((cert) => cert.validForDate(this.timestamp));
|
|
907
|
+
if (!validForDate) {
|
|
908
|
+
throw new Error("certificate is not valid or expired at the specified date");
|
|
909
|
+
}
|
|
910
|
+
return certificatePath;
|
|
911
|
+
}
|
|
912
|
+
async sort() {
|
|
913
|
+
const leafCert = this.untrustedCert;
|
|
914
|
+
let paths = await this.buildPaths(leafCert);
|
|
915
|
+
paths = paths.filter((path2) => path2.some((cert) => this.trustedCerts.includes(cert)));
|
|
916
|
+
if (paths.length === 0) {
|
|
917
|
+
throw new Error("no trusted certificate path found");
|
|
918
|
+
}
|
|
919
|
+
const path = paths.reduce((prev, curr) => prev.length < curr.length ? prev : curr);
|
|
920
|
+
return [leafCert, ...path].slice(0, -1);
|
|
921
|
+
}
|
|
922
|
+
async buildPaths(certificate) {
|
|
923
|
+
const paths = [];
|
|
924
|
+
const issuers = await this.findIssuer(certificate);
|
|
925
|
+
if (issuers.length === 0) {
|
|
926
|
+
throw new Error("no valid certificate path found");
|
|
927
|
+
}
|
|
928
|
+
for (let i = 0; i < issuers.length; i++) {
|
|
929
|
+
const issuer = issuers[i];
|
|
930
|
+
if (issuer.equals(certificate)) {
|
|
931
|
+
paths.push([certificate]);
|
|
932
|
+
continue;
|
|
933
|
+
}
|
|
934
|
+
const subPaths = await this.buildPaths(issuer);
|
|
935
|
+
for (let j = 0; j < subPaths.length; j++) {
|
|
936
|
+
paths.push([issuer, ...subPaths[j]]);
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
return paths;
|
|
940
|
+
}
|
|
941
|
+
async findIssuer(certificate) {
|
|
942
|
+
let issuers = [];
|
|
943
|
+
let keyIdentifier;
|
|
944
|
+
if (uint8ArrayEqual(certificate.subject, certificate.issuer)) {
|
|
945
|
+
if (await certificate.verify()) {
|
|
946
|
+
return [certificate];
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
if (certificate.extAuthorityKeyID) {
|
|
950
|
+
keyIdentifier = certificate.extAuthorityKeyID.keyIdentifier;
|
|
951
|
+
}
|
|
952
|
+
this.localCerts.forEach((possibleIssuer) => {
|
|
953
|
+
if (keyIdentifier) {
|
|
954
|
+
if (possibleIssuer.extSubjectKeyID) {
|
|
955
|
+
if (uint8ArrayEqual(possibleIssuer.extSubjectKeyID.keyIdentifier, keyIdentifier)) {
|
|
956
|
+
issuers.push(possibleIssuer);
|
|
957
|
+
}
|
|
958
|
+
return;
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
if (uint8ArrayEqual(possibleIssuer.subject, certificate.issuer)) {
|
|
962
|
+
issuers.push(possibleIssuer);
|
|
963
|
+
}
|
|
964
|
+
});
|
|
965
|
+
const verifiedIssuers = [];
|
|
966
|
+
for (const issuer of issuers) {
|
|
967
|
+
try {
|
|
968
|
+
if (await certificate.verify(issuer)) {
|
|
969
|
+
verifiedIssuers.push(issuer);
|
|
970
|
+
}
|
|
971
|
+
} catch (ex) {
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
return verifiedIssuers;
|
|
975
|
+
}
|
|
976
|
+
checkPath(path) {
|
|
977
|
+
if (path.length < 1) {
|
|
978
|
+
throw new Error("certificate chain must contain at least one certificate");
|
|
979
|
+
}
|
|
980
|
+
const validCAs = path.slice(1).every((cert) => cert.isCA);
|
|
981
|
+
if (!validCAs) {
|
|
982
|
+
throw new Error("intermediate certificate is not a CA");
|
|
983
|
+
}
|
|
984
|
+
for (let i = path.length - 2; i >= 0; i--) {
|
|
985
|
+
if (!uint8ArrayEqual(path[i].issuer, path[i + 1].subject)) {
|
|
986
|
+
throw new Error("incorrect certificate name chaining");
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
for (let i = 0; i < path.length; i++) {
|
|
990
|
+
const cert = path[i];
|
|
991
|
+
if (cert.extBasicConstraints?.isCA) {
|
|
992
|
+
const pathLength = cert.extBasicConstraints.pathLenConstraint;
|
|
993
|
+
if (pathLength !== void 0 && pathLength < BigInt(i - 1)) {
|
|
994
|
+
throw new Error("path length constraint exceeded");
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
};
|
|
1000
|
+
function dedupeCertificates(certs) {
|
|
1001
|
+
for (let i = 0; i < certs.length; i++) {
|
|
1002
|
+
for (let j = i + 1; j < certs.length; j++) {
|
|
1003
|
+
if (certs[i].equals(certs[j])) {
|
|
1004
|
+
certs.splice(j, 1);
|
|
1005
|
+
j--;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
return certs;
|
|
1010
|
+
}
|
|
1011
|
+
__name(dedupeCertificates, "dedupeCertificates");
|
|
1012
|
+
|
|
1013
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/dsse.js
|
|
1014
|
+
var PAE_PREFIX = "DSSEv1";
|
|
1015
|
+
function preAuthEncoding(payloadType, payload) {
|
|
1016
|
+
const prefix = [
|
|
1017
|
+
PAE_PREFIX,
|
|
1018
|
+
payloadType.length,
|
|
1019
|
+
payloadType,
|
|
1020
|
+
payload.length,
|
|
1021
|
+
""
|
|
1022
|
+
].join(" ");
|
|
1023
|
+
const encoder = new TextEncoder();
|
|
1024
|
+
const prefixBuffer = encoder.encode(prefix);
|
|
1025
|
+
for (let i = 0; i < prefixBuffer.length; i++) {
|
|
1026
|
+
if (prefixBuffer[i] > 127) {
|
|
1027
|
+
throw new Error(`Invalid non-ASCII character in PAE prefix at position ${i}`);
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
const combinedArray = new Uint8Array(prefixBuffer.length + payload.length);
|
|
1031
|
+
combinedArray.set(prefixBuffer, 0);
|
|
1032
|
+
combinedArray.set(payload, prefixBuffer.length);
|
|
1033
|
+
return combinedArray;
|
|
1034
|
+
}
|
|
1035
|
+
__name(preAuthEncoding, "preAuthEncoding");
|
|
1036
|
+
|
|
1037
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/tlog/merkle.js
|
|
1038
|
+
var RFC6962_LEAF_HASH_PREFIX = new Uint8Array([0]);
|
|
1039
|
+
var RFC6962_NODE_HASH_PREFIX = new Uint8Array([1]);
|
|
1040
|
+
async function verifyMerkleInclusion(entry) {
|
|
1041
|
+
if (!entry.inclusionProof) {
|
|
1042
|
+
throw new Error("Missing inclusion proof");
|
|
1043
|
+
}
|
|
1044
|
+
const inclusionProof = entry.inclusionProof;
|
|
1045
|
+
const logIndex = BigInt(inclusionProof.logIndex);
|
|
1046
|
+
const treeSize = BigInt(inclusionProof.treeSize);
|
|
1047
|
+
if (logIndex < 0n || logIndex >= treeSize) {
|
|
1048
|
+
throw new Error(`Invalid log index: ${logIndex}`);
|
|
1049
|
+
}
|
|
1050
|
+
const { inner, border } = decompInclProof(logIndex, treeSize);
|
|
1051
|
+
if (inclusionProof.hashes.length !== inner + border) {
|
|
1052
|
+
throw new Error("Invalid hash count in inclusion proof");
|
|
1053
|
+
}
|
|
1054
|
+
const innerHashes = inclusionProof.hashes.slice(0, inner).map((h) => base64ToUint8Array(h));
|
|
1055
|
+
const borderHashes = inclusionProof.hashes.slice(inner).map((h) => base64ToUint8Array(h));
|
|
1056
|
+
const leafHash = await hashLeaf(base64ToUint8Array(entry.canonicalizedBody));
|
|
1057
|
+
const calculatedHash = await chainBorderRight(await chainInner(leafHash, innerHashes, logIndex), borderHashes);
|
|
1058
|
+
const rootHash = base64ToUint8Array(inclusionProof.rootHash);
|
|
1059
|
+
if (!uint8ArrayEqual(calculatedHash, rootHash)) {
|
|
1060
|
+
throw new Error("Calculated root hash does not match inclusion proof");
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
__name(verifyMerkleInclusion, "verifyMerkleInclusion");
|
|
1064
|
+
function decompInclProof(index, size) {
|
|
1065
|
+
const inner = innerProofSize(index, size);
|
|
1066
|
+
const border = onesCount(index >> BigInt(inner));
|
|
1067
|
+
return { inner, border };
|
|
1068
|
+
}
|
|
1069
|
+
__name(decompInclProof, "decompInclProof");
|
|
1070
|
+
async function chainInner(seed, hashes, index) {
|
|
1071
|
+
let acc = seed;
|
|
1072
|
+
for (let i = 0; i < hashes.length; i++) {
|
|
1073
|
+
const h = hashes[i];
|
|
1074
|
+
if (index >> BigInt(i) & BigInt(1)) {
|
|
1075
|
+
acc = await hashChildren(h, acc);
|
|
1076
|
+
} else {
|
|
1077
|
+
acc = await hashChildren(acc, h);
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
return acc;
|
|
1081
|
+
}
|
|
1082
|
+
__name(chainInner, "chainInner");
|
|
1083
|
+
async function chainBorderRight(seed, hashes) {
|
|
1084
|
+
let acc = seed;
|
|
1085
|
+
for (const h of hashes) {
|
|
1086
|
+
acc = await hashChildren(h, acc);
|
|
1087
|
+
}
|
|
1088
|
+
return acc;
|
|
1089
|
+
}
|
|
1090
|
+
__name(chainBorderRight, "chainBorderRight");
|
|
1091
|
+
function innerProofSize(index, size) {
|
|
1092
|
+
return bitLength(index ^ size - BigInt(1));
|
|
1093
|
+
}
|
|
1094
|
+
__name(innerProofSize, "innerProofSize");
|
|
1095
|
+
function onesCount(num) {
|
|
1096
|
+
return num.toString(2).split("1").length - 1;
|
|
1097
|
+
}
|
|
1098
|
+
__name(onesCount, "onesCount");
|
|
1099
|
+
function bitLength(n) {
|
|
1100
|
+
if (n === 0n) {
|
|
1101
|
+
return 0;
|
|
1102
|
+
}
|
|
1103
|
+
return n.toString(2).length;
|
|
1104
|
+
}
|
|
1105
|
+
__name(bitLength, "bitLength");
|
|
1106
|
+
async function hashChildren(left, right) {
|
|
1107
|
+
const data = new Uint8Array(RFC6962_NODE_HASH_PREFIX.length + left.length + right.length);
|
|
1108
|
+
data.set(RFC6962_NODE_HASH_PREFIX, 0);
|
|
1109
|
+
data.set(left, RFC6962_NODE_HASH_PREFIX.length);
|
|
1110
|
+
data.set(right, RFC6962_NODE_HASH_PREFIX.length + left.length);
|
|
1111
|
+
const hash = await crypto.subtle.digest(HashAlgorithms.SHA256, data);
|
|
1112
|
+
return new Uint8Array(hash);
|
|
1113
|
+
}
|
|
1114
|
+
__name(hashChildren, "hashChildren");
|
|
1115
|
+
async function hashLeaf(leaf) {
|
|
1116
|
+
const data = new Uint8Array(RFC6962_LEAF_HASH_PREFIX.length + leaf.length);
|
|
1117
|
+
data.set(RFC6962_LEAF_HASH_PREFIX, 0);
|
|
1118
|
+
data.set(leaf, RFC6962_LEAF_HASH_PREFIX.length);
|
|
1119
|
+
const hash = await crypto.subtle.digest(HashAlgorithms.SHA256, data);
|
|
1120
|
+
return new Uint8Array(hash);
|
|
1121
|
+
}
|
|
1122
|
+
__name(hashLeaf, "hashLeaf");
|
|
1123
|
+
|
|
1124
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/tlog/checkpoint.js
|
|
1125
|
+
var CHECKPOINT_SEPARATOR = "\n\n";
|
|
1126
|
+
var SIGNATURE_REGEX = /\u2014 (\S+) (\S+)\n/g;
|
|
1127
|
+
var SignedNote = class _SignedNote {
|
|
1128
|
+
static {
|
|
1129
|
+
__name(this, "SignedNote");
|
|
1130
|
+
}
|
|
1131
|
+
constructor(note, signatures) {
|
|
1132
|
+
this.note = note;
|
|
1133
|
+
this.signatures = signatures;
|
|
1134
|
+
}
|
|
1135
|
+
static fromString(envelope) {
|
|
1136
|
+
if (!envelope.includes(CHECKPOINT_SEPARATOR)) {
|
|
1137
|
+
throw new Error("Missing checkpoint separator");
|
|
1138
|
+
}
|
|
1139
|
+
const split = envelope.indexOf(CHECKPOINT_SEPARATOR);
|
|
1140
|
+
const header = envelope.slice(0, split + 1);
|
|
1141
|
+
const data = envelope.slice(split + CHECKPOINT_SEPARATOR.length);
|
|
1142
|
+
const matches = data.matchAll(SIGNATURE_REGEX);
|
|
1143
|
+
const signatures = [];
|
|
1144
|
+
for (const match of matches) {
|
|
1145
|
+
const [, name, signature] = match;
|
|
1146
|
+
const sigBytes = base64ToUint8Array(signature);
|
|
1147
|
+
if (sigBytes.length < 5) {
|
|
1148
|
+
throw new Error("Malformed checkpoint signature");
|
|
1149
|
+
}
|
|
1150
|
+
signatures.push({
|
|
1151
|
+
name,
|
|
1152
|
+
keyHint: sigBytes.subarray(0, 4),
|
|
1153
|
+
signature: sigBytes.subarray(4)
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
if (signatures.length === 0) {
|
|
1157
|
+
throw new Error("No signatures found in checkpoint");
|
|
1158
|
+
}
|
|
1159
|
+
return new _SignedNote(header, signatures);
|
|
1160
|
+
}
|
|
1161
|
+
};
|
|
1162
|
+
var LogCheckpoint = class _LogCheckpoint {
|
|
1163
|
+
static {
|
|
1164
|
+
__name(this, "LogCheckpoint");
|
|
1165
|
+
}
|
|
1166
|
+
constructor(origin, logSize, logHash, rest) {
|
|
1167
|
+
this.origin = origin;
|
|
1168
|
+
this.logSize = logSize;
|
|
1169
|
+
this.logHash = logHash;
|
|
1170
|
+
this.rest = rest;
|
|
1171
|
+
}
|
|
1172
|
+
static fromString(note) {
|
|
1173
|
+
const lines = note.trimEnd().split("\n");
|
|
1174
|
+
if (lines.length < 3) {
|
|
1175
|
+
throw new Error("Too few lines in checkpoint header");
|
|
1176
|
+
}
|
|
1177
|
+
const origin = lines[0];
|
|
1178
|
+
const logSize = BigInt(lines[1]);
|
|
1179
|
+
const rootHash = base64ToUint8Array(lines[2]);
|
|
1180
|
+
const rest = lines.slice(3);
|
|
1181
|
+
return new _LogCheckpoint(origin, logSize, rootHash, rest);
|
|
1182
|
+
}
|
|
1183
|
+
};
|
|
1184
|
+
async function verifyCheckpoint(entry, tlogs) {
|
|
1185
|
+
if (!entry.inclusionProof?.checkpoint) {
|
|
1186
|
+
throw new Error("Missing checkpoint in inclusion proof");
|
|
1187
|
+
}
|
|
1188
|
+
const entryLogId = base64ToUint8Array(entry.logId.keyId);
|
|
1189
|
+
const matchingTLogs = tlogs.filter((tlog) => {
|
|
1190
|
+
const tlogId = base64ToUint8Array(tlog.logId.keyId);
|
|
1191
|
+
return uint8ArrayEqual(tlogId, entryLogId);
|
|
1192
|
+
});
|
|
1193
|
+
const validTLogs = entry.integratedTime ? filterTLogsByDate(matchingTLogs, new Date(Number(entry.integratedTime) * 1e3)) : matchingTLogs;
|
|
1194
|
+
const inclusionProof = entry.inclusionProof;
|
|
1195
|
+
const signedNote = SignedNote.fromString(inclusionProof.checkpoint.envelope);
|
|
1196
|
+
const checkpoint = LogCheckpoint.fromString(signedNote.note);
|
|
1197
|
+
if (!await verifySignedNote(signedNote, validTLogs)) {
|
|
1198
|
+
throw new Error("Invalid checkpoint signature");
|
|
1199
|
+
}
|
|
1200
|
+
const rootHash = base64ToUint8Array(inclusionProof.rootHash);
|
|
1201
|
+
if (!uint8ArrayEqual(checkpoint.logHash, rootHash)) {
|
|
1202
|
+
throw new Error("Root hash mismatch between checkpoint and inclusion proof");
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
__name(verifyCheckpoint, "verifyCheckpoint");
|
|
1206
|
+
async function verifySignedNote(signedNote, tlogs) {
|
|
1207
|
+
const data = stringToUint8Array(signedNote.note);
|
|
1208
|
+
let hasValidSignature = false;
|
|
1209
|
+
for (const signature of signedNote.signatures) {
|
|
1210
|
+
const tlog = tlogs.find((tlog2) => {
|
|
1211
|
+
const logId = base64ToUint8Array(tlog2.logId.keyId);
|
|
1212
|
+
return uint8ArrayEqual(logId.subarray(0, 4), signature.keyHint);
|
|
1213
|
+
});
|
|
1214
|
+
if (!tlog) {
|
|
1215
|
+
continue;
|
|
1216
|
+
}
|
|
1217
|
+
const publicKey = await importTLogKey(tlog);
|
|
1218
|
+
const verified = await verifySignature(publicKey, data, signature.signature, tlog.hashAlgorithm);
|
|
1219
|
+
if (verified) {
|
|
1220
|
+
hasValidSignature = true;
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
return hasValidSignature;
|
|
1224
|
+
}
|
|
1225
|
+
__name(verifySignedNote, "verifySignedNote");
|
|
1226
|
+
function filterTLogsByDate(tlogs, targetDate) {
|
|
1227
|
+
return tlogs.filter((tlog) => {
|
|
1228
|
+
const start = new Date(tlog.publicKey.validFor.start);
|
|
1229
|
+
const end = tlog.publicKey.validFor.end ? new Date(tlog.publicKey.validFor.end) : null;
|
|
1230
|
+
return targetDate >= start && (!end || targetDate <= end);
|
|
1231
|
+
});
|
|
1232
|
+
}
|
|
1233
|
+
__name(filterTLogsByDate, "filterTLogsByDate");
|
|
1234
|
+
async function importTLogKey(tlog) {
|
|
1235
|
+
const keyDetails = tlog.publicKey.keyDetails;
|
|
1236
|
+
let keyType;
|
|
1237
|
+
let scheme;
|
|
1238
|
+
if (keyDetails === "ecdsa-sha2-nistp256") {
|
|
1239
|
+
keyType = KeyTypes.Ecdsa;
|
|
1240
|
+
scheme = "P256-SHA256";
|
|
1241
|
+
} else if (keyDetails.includes("ECDSA")) {
|
|
1242
|
+
keyType = KeyTypes.Ecdsa;
|
|
1243
|
+
scheme = keyDetails.replace("PKIX_ECDSA_", "").replace(/_/g, "-");
|
|
1244
|
+
} else if (keyDetails.includes("ED25519")) {
|
|
1245
|
+
keyType = KeyTypes.Ed25519;
|
|
1246
|
+
scheme = KeyTypes.Ed25519;
|
|
1247
|
+
} else if (keyDetails.includes("RSA")) {
|
|
1248
|
+
keyType = KeyTypes.RSA;
|
|
1249
|
+
scheme = keyDetails.replace("PKIX_RSA_", "").replace(/_/g, "-");
|
|
1250
|
+
} else {
|
|
1251
|
+
throw new Error(`Unsupported key type in keyDetails: ${keyDetails}`);
|
|
1252
|
+
}
|
|
1253
|
+
return importKey(keyType, scheme, tlog.publicKey.rawBytes);
|
|
1254
|
+
}
|
|
1255
|
+
__name(importTLogKey, "importTLogKey");
|
|
1256
|
+
|
|
1257
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/tlog/hashedrekord.js
|
|
1258
|
+
async function verifyHashedRekordBody(entry, bundle) {
|
|
1259
|
+
const hashedRekordEntry = entry;
|
|
1260
|
+
switch (hashedRekordEntry.apiVersion) {
|
|
1261
|
+
case "0.0.1":
|
|
1262
|
+
return verifyHashedRekordV001Body(hashedRekordEntry, bundle);
|
|
1263
|
+
case "0.0.2":
|
|
1264
|
+
return verifyHashedRekordV002Body(hashedRekordEntry, bundle);
|
|
1265
|
+
default:
|
|
1266
|
+
throw new Error(`Unsupported hashedrekord version: ${hashedRekordEntry.apiVersion}`);
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
__name(verifyHashedRekordBody, "verifyHashedRekordBody");
|
|
1270
|
+
function verifyHashedRekordV001Body(entry, bundle) {
|
|
1271
|
+
const spec = entry.spec;
|
|
1272
|
+
if (!bundle.messageSignature) {
|
|
1273
|
+
throw new Error("Bundle missing messageSignature for hashedrekord entry");
|
|
1274
|
+
}
|
|
1275
|
+
const tlogSig = spec.signature.content || "";
|
|
1276
|
+
const tlogSigBytes = base64ToUint8Array(tlogSig);
|
|
1277
|
+
const bundleSigBytes = base64ToUint8Array(bundle.messageSignature.signature);
|
|
1278
|
+
if (!uint8ArrayEqual(tlogSigBytes, bundleSigBytes)) {
|
|
1279
|
+
throw new Error("Signature mismatch between TLog entry and bundle");
|
|
1280
|
+
}
|
|
1281
|
+
const tlogDigest = spec.data.hash?.value || "";
|
|
1282
|
+
const tlogDigestBytes = hexToUint8Array(tlogDigest);
|
|
1283
|
+
const bundleDigestBytes = base64ToUint8Array(bundle.messageSignature.messageDigest.digest);
|
|
1284
|
+
if (!uint8ArrayEqual(tlogDigestBytes, bundleDigestBytes)) {
|
|
1285
|
+
throw new Error("Digest mismatch between TLog entry and bundle");
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
__name(verifyHashedRekordV001Body, "verifyHashedRekordV001Body");
|
|
1289
|
+
function verifyHashedRekordV002Body(entry, bundle) {
|
|
1290
|
+
const spec = entry.spec.hashedRekordV002;
|
|
1291
|
+
if (!bundle.messageSignature) {
|
|
1292
|
+
throw new Error("Bundle missing messageSignature for hashedrekord v0.0.2 entry");
|
|
1293
|
+
}
|
|
1294
|
+
const tlogSig = spec.signature.content || "";
|
|
1295
|
+
const tlogSigBytes = base64ToUint8Array(tlogSig);
|
|
1296
|
+
const bundleSigBytes = base64ToUint8Array(bundle.messageSignature.signature);
|
|
1297
|
+
if (!uint8ArrayEqual(tlogSigBytes, bundleSigBytes)) {
|
|
1298
|
+
throw new Error("Signature mismatch between TLog entry and bundle (v0.0.2)");
|
|
1299
|
+
}
|
|
1300
|
+
const tlogDigest = spec.data.digest || "";
|
|
1301
|
+
const tlogDigestBytes = base64ToUint8Array(tlogDigest);
|
|
1302
|
+
const bundleDigestBytes = base64ToUint8Array(bundle.messageSignature.messageDigest.digest);
|
|
1303
|
+
if (!uint8ArrayEqual(tlogDigestBytes, bundleDigestBytes)) {
|
|
1304
|
+
throw new Error("Digest mismatch between TLog entry and bundle (v0.0.2)");
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
__name(verifyHashedRekordV002Body, "verifyHashedRekordV002Body");
|
|
1308
|
+
|
|
1309
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/tlog/dsse.js
|
|
1310
|
+
async function verifyDSSEBody(entry, bundle) {
|
|
1311
|
+
const dsseEntry = entry;
|
|
1312
|
+
switch (dsseEntry.apiVersion) {
|
|
1313
|
+
case "0.0.1":
|
|
1314
|
+
return verifyDSSE001Body(dsseEntry, bundle);
|
|
1315
|
+
case "0.0.2":
|
|
1316
|
+
return verifyDSSE002Body(dsseEntry, bundle);
|
|
1317
|
+
default:
|
|
1318
|
+
throw new Error(`Unsupported dsse version: ${dsseEntry.apiVersion}`);
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
__name(verifyDSSEBody, "verifyDSSEBody");
|
|
1322
|
+
async function verifyDSSE001Body(entry, bundle) {
|
|
1323
|
+
if (!bundle.dsseEnvelope) {
|
|
1324
|
+
throw new Error("Bundle missing dsseEnvelope for DSSE entry");
|
|
1325
|
+
}
|
|
1326
|
+
if (!entry.spec.signatures || entry.spec.signatures.length !== 1) {
|
|
1327
|
+
throw new Error("DSSE entry must have exactly one signature");
|
|
1328
|
+
}
|
|
1329
|
+
const tlogSig = entry.spec.signatures[0].signature;
|
|
1330
|
+
const tlogSigBytes = base64ToUint8Array(tlogSig);
|
|
1331
|
+
if (bundle.dsseEnvelope.signatures.length === 0) {
|
|
1332
|
+
throw new Error("Bundle DSSE envelope missing signatures");
|
|
1333
|
+
}
|
|
1334
|
+
const bundleSigBytes = base64ToUint8Array(bundle.dsseEnvelope.signatures[0].sig);
|
|
1335
|
+
if (!uint8ArrayEqual(tlogSigBytes, bundleSigBytes)) {
|
|
1336
|
+
throw new Error("DSSE signature mismatch between TLog entry and bundle");
|
|
1337
|
+
}
|
|
1338
|
+
if (!entry.spec.payloadHash?.value || !entry.spec.payloadHash?.algorithm) {
|
|
1339
|
+
throw new Error("DSSE entry missing payloadHash or algorithm");
|
|
1340
|
+
}
|
|
1341
|
+
const hashAlg = getHashAlgorithm(entry.spec.payloadHash.algorithm);
|
|
1342
|
+
const tlogHashBytes = hexToUint8Array(entry.spec.payloadHash.value);
|
|
1343
|
+
const payloadBytes = base64ToUint8Array(bundle.dsseEnvelope.payload);
|
|
1344
|
+
const bundleHashBytes = new Uint8Array(await crypto.subtle.digest(hashAlg, payloadBytes));
|
|
1345
|
+
if (!uint8ArrayEqual(tlogHashBytes, bundleHashBytes)) {
|
|
1346
|
+
throw new Error("DSSE payload hash mismatch between TLog entry and bundle");
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
__name(verifyDSSE001Body, "verifyDSSE001Body");
|
|
1350
|
+
async function verifyDSSE002Body(entry, bundle) {
|
|
1351
|
+
if (!bundle.dsseEnvelope) {
|
|
1352
|
+
throw new Error("Bundle missing dsseEnvelope for DSSE v0.0.2 entry");
|
|
1353
|
+
}
|
|
1354
|
+
const spec = entry.spec.dsseV002;
|
|
1355
|
+
if (!spec) {
|
|
1356
|
+
throw new Error("DSSE v0.0.2 entry missing dsseV002 spec");
|
|
1357
|
+
}
|
|
1358
|
+
if (!spec.signatures || spec.signatures.length !== 1) {
|
|
1359
|
+
throw new Error("DSSE v0.0.2 entry must have exactly one signature");
|
|
1360
|
+
}
|
|
1361
|
+
const tlogSig = spec.signatures[0].content;
|
|
1362
|
+
const tlogSigBytes = base64ToUint8Array(tlogSig);
|
|
1363
|
+
if (bundle.dsseEnvelope.signatures.length === 0) {
|
|
1364
|
+
throw new Error("Bundle DSSE envelope missing signatures");
|
|
1365
|
+
}
|
|
1366
|
+
const bundleSigBytes = base64ToUint8Array(bundle.dsseEnvelope.signatures[0].sig);
|
|
1367
|
+
if (!uint8ArrayEqual(tlogSigBytes, bundleSigBytes)) {
|
|
1368
|
+
throw new Error("DSSE signature mismatch between TLog entry and bundle (v0.0.2)");
|
|
1369
|
+
}
|
|
1370
|
+
if (!spec.payloadHash?.digest || !spec.payloadHash?.algorithm) {
|
|
1371
|
+
throw new Error("DSSE v0.0.2 entry missing payloadHash or algorithm");
|
|
1372
|
+
}
|
|
1373
|
+
const hashAlg = getHashAlgorithm(spec.payloadHash.algorithm);
|
|
1374
|
+
const tlogHashBytes = base64ToUint8Array(spec.payloadHash.digest);
|
|
1375
|
+
const payloadBytes = base64ToUint8Array(bundle.dsseEnvelope.payload);
|
|
1376
|
+
const bundleHashBytes = new Uint8Array(await crypto.subtle.digest(hashAlg, payloadBytes));
|
|
1377
|
+
if (!uint8ArrayEqual(tlogHashBytes, bundleHashBytes)) {
|
|
1378
|
+
throw new Error("DSSE payload hash mismatch between TLog entry and bundle (v0.0.2)");
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
__name(verifyDSSE002Body, "verifyDSSE002Body");
|
|
1382
|
+
|
|
1383
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/tlog/intoto.js
|
|
1384
|
+
async function verifyIntotoBody(entry, bundle) {
|
|
1385
|
+
const intotoEntry = entry;
|
|
1386
|
+
if (intotoEntry.apiVersion !== "0.0.2") {
|
|
1387
|
+
throw new Error(`Unsupported intoto version: ${intotoEntry.apiVersion}`);
|
|
1388
|
+
}
|
|
1389
|
+
if (!bundle.dsseEnvelope) {
|
|
1390
|
+
throw new Error("Bundle missing dsseEnvelope for intoto entry");
|
|
1391
|
+
}
|
|
1392
|
+
const tlogEnvelope = intotoEntry.spec.content.envelope;
|
|
1393
|
+
if (!tlogEnvelope.signatures || tlogEnvelope.signatures.length !== 1) {
|
|
1394
|
+
throw new Error("Intoto entry must have exactly one signature");
|
|
1395
|
+
}
|
|
1396
|
+
const tlogSigBase64 = tlogEnvelope.signatures[0].sig;
|
|
1397
|
+
const tlogSigDecoded = base64Decode(tlogSigBase64);
|
|
1398
|
+
const tlogSigBytes = base64ToUint8Array(tlogSigDecoded);
|
|
1399
|
+
if (bundle.dsseEnvelope.signatures.length === 0) {
|
|
1400
|
+
throw new Error("Bundle DSSE envelope missing signatures");
|
|
1401
|
+
}
|
|
1402
|
+
const bundleSigBytes = base64ToUint8Array(bundle.dsseEnvelope.signatures[0].sig);
|
|
1403
|
+
if (!uint8ArrayEqual(tlogSigBytes, bundleSigBytes)) {
|
|
1404
|
+
throw new Error("Intoto signature mismatch between TLog entry and bundle");
|
|
1405
|
+
}
|
|
1406
|
+
if (intotoEntry.spec.content.payloadHash) {
|
|
1407
|
+
if (!intotoEntry.spec.content.payloadHash.algorithm) {
|
|
1408
|
+
throw new Error("Intoto entry missing payloadHash algorithm");
|
|
1409
|
+
}
|
|
1410
|
+
const hashAlg = getHashAlgorithm(intotoEntry.spec.content.payloadHash.algorithm);
|
|
1411
|
+
const tlogHashBytes = hexToUint8Array(intotoEntry.spec.content.payloadHash.value);
|
|
1412
|
+
const payloadBytes = base64ToUint8Array(bundle.dsseEnvelope.payload);
|
|
1413
|
+
const bundleHashBytes = new Uint8Array(await crypto.subtle.digest(hashAlg, payloadBytes));
|
|
1414
|
+
if (!uint8ArrayEqual(tlogHashBytes, bundleHashBytes)) {
|
|
1415
|
+
throw new Error("Intoto payload hash mismatch between TLog entry and bundle");
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
__name(verifyIntotoBody, "verifyIntotoBody");
|
|
1420
|
+
|
|
1421
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/tlog/body.js
|
|
1422
|
+
async function verifyTLogBody(entry, bundle) {
|
|
1423
|
+
const rekorEntry = parseCanonicalBody(entry);
|
|
1424
|
+
const { kind, version } = entry.kindVersion;
|
|
1425
|
+
if (kind !== rekorEntry.kind || version !== rekorEntry.apiVersion) {
|
|
1426
|
+
throw new Error(`kind/version mismatch - expected: ${kind}/${version}, received: ${rekorEntry.kind}/${rekorEntry.apiVersion}`);
|
|
1427
|
+
}
|
|
1428
|
+
switch (rekorEntry.kind) {
|
|
1429
|
+
case "hashedrekord":
|
|
1430
|
+
return verifyHashedRekordBody(rekorEntry, bundle);
|
|
1431
|
+
case "dsse":
|
|
1432
|
+
return verifyDSSEBody(rekorEntry, bundle);
|
|
1433
|
+
case "intoto":
|
|
1434
|
+
return verifyIntotoBody(rekorEntry, bundle);
|
|
1435
|
+
default:
|
|
1436
|
+
throw new Error(`Unsupported TLog entry kind: ${rekorEntry.kind}`);
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
__name(verifyTLogBody, "verifyTLogBody");
|
|
1440
|
+
function parseCanonicalBody(entry) {
|
|
1441
|
+
try {
|
|
1442
|
+
const decodedBody = base64Decode(entry.canonicalizedBody);
|
|
1443
|
+
const rekorEntry = JSON.parse(decodedBody);
|
|
1444
|
+
if (!rekorEntry.apiVersion || !rekorEntry.kind || !rekorEntry.spec) {
|
|
1445
|
+
throw new Error("Invalid Rekor entry structure");
|
|
1446
|
+
}
|
|
1447
|
+
return rekorEntry;
|
|
1448
|
+
} catch (error) {
|
|
1449
|
+
throw new Error(`Failed to parse canonicalized body: ${error instanceof Error ? error.message : String(error)}`);
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
__name(parseCanonicalBody, "parseCanonicalBody");
|
|
1453
|
+
|
|
1454
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/rfc3161/error.js
|
|
1455
|
+
var RFC3161TimestampVerificationError = class extends Error {
|
|
1456
|
+
static {
|
|
1457
|
+
__name(this, "RFC3161TimestampVerificationError");
|
|
1458
|
+
}
|
|
1459
|
+
};
|
|
1460
|
+
|
|
1461
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/rfc3161/tstinfo.js
|
|
1462
|
+
var TSTInfo = class {
|
|
1463
|
+
static {
|
|
1464
|
+
__name(this, "TSTInfo");
|
|
1465
|
+
}
|
|
1466
|
+
constructor(asn1) {
|
|
1467
|
+
this.root = asn1;
|
|
1468
|
+
}
|
|
1469
|
+
get version() {
|
|
1470
|
+
return this.root.subs[0].toInteger();
|
|
1471
|
+
}
|
|
1472
|
+
get genTime() {
|
|
1473
|
+
return this.root.subs[4].toDate();
|
|
1474
|
+
}
|
|
1475
|
+
get messageImprintHashAlgorithm() {
|
|
1476
|
+
const oid = this.messageImprintObj.subs[0].subs[0].toOID();
|
|
1477
|
+
const algo = SHA2_HASH_ALGOS[oid];
|
|
1478
|
+
if (!algo) {
|
|
1479
|
+
throw new Error(`Unknown message imprint hash algorithm OID: ${oid}`);
|
|
1480
|
+
}
|
|
1481
|
+
return algo;
|
|
1482
|
+
}
|
|
1483
|
+
get messageImprintHashedMessage() {
|
|
1484
|
+
return this.messageImprintObj.subs[1].value;
|
|
1485
|
+
}
|
|
1486
|
+
get raw() {
|
|
1487
|
+
return this.root.toDER();
|
|
1488
|
+
}
|
|
1489
|
+
async verify(data) {
|
|
1490
|
+
const hashAlg = this.messageImprintHashAlgorithm;
|
|
1491
|
+
const hashAlgName = hashAlg === "sha256" ? HashAlgorithms.SHA256 : hashAlg === "sha384" ? HashAlgorithms.SHA384 : hashAlg === "sha512" ? HashAlgorithms.SHA512 : hashAlg;
|
|
1492
|
+
const digest = await crypto.subtle.digest(hashAlgName, data);
|
|
1493
|
+
if (!uint8ArrayEqual(new Uint8Array(digest), this.messageImprintHashedMessage)) {
|
|
1494
|
+
throw new RFC3161TimestampVerificationError("message imprint does not match artifact");
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
// https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2
|
|
1498
|
+
get messageImprintObj() {
|
|
1499
|
+
return this.root.subs[2];
|
|
1500
|
+
}
|
|
1501
|
+
};
|
|
1502
|
+
|
|
1503
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/rfc3161/timestamp.js
|
|
1504
|
+
var OID_PKCS9_CONTENT_TYPE_SIGNED_DATA = "1.2.840.113549.1.7.2";
|
|
1505
|
+
var OID_PKCS9_CONTENT_TYPE_TSTINFO = "1.2.840.113549.1.9.16.1.4";
|
|
1506
|
+
var OID_PKCS9_MESSAGE_DIGEST_KEY = "1.2.840.113549.1.9.4";
|
|
1507
|
+
var RFC3161Timestamp = class _RFC3161Timestamp {
|
|
1508
|
+
static {
|
|
1509
|
+
__name(this, "RFC3161Timestamp");
|
|
1510
|
+
}
|
|
1511
|
+
constructor(asn1) {
|
|
1512
|
+
this.root = asn1;
|
|
1513
|
+
}
|
|
1514
|
+
static parse(der) {
|
|
1515
|
+
const asn1 = ASN1Obj.parseBuffer(der);
|
|
1516
|
+
return new _RFC3161Timestamp(asn1);
|
|
1517
|
+
}
|
|
1518
|
+
get status() {
|
|
1519
|
+
return this.pkiStatusInfoObj.subs[0].toInteger();
|
|
1520
|
+
}
|
|
1521
|
+
get contentType() {
|
|
1522
|
+
return this.contentTypeObj.toOID();
|
|
1523
|
+
}
|
|
1524
|
+
get eContentType() {
|
|
1525
|
+
return this.eContentTypeObj.toOID();
|
|
1526
|
+
}
|
|
1527
|
+
get signingTime() {
|
|
1528
|
+
return this.tstInfo.genTime;
|
|
1529
|
+
}
|
|
1530
|
+
get signerIssuer() {
|
|
1531
|
+
return this.signerSidObj.subs[0].value;
|
|
1532
|
+
}
|
|
1533
|
+
get signerSerialNumber() {
|
|
1534
|
+
return this.signerSidObj.subs[1].value;
|
|
1535
|
+
}
|
|
1536
|
+
get signerDigestAlgorithm() {
|
|
1537
|
+
const oid = this.signerDigestAlgorithmObj.subs[0].toOID();
|
|
1538
|
+
const algo = SHA2_HASH_ALGOS[oid];
|
|
1539
|
+
if (!algo) {
|
|
1540
|
+
throw new Error(`Unknown digest algorithm OID: ${oid}`);
|
|
1541
|
+
}
|
|
1542
|
+
return algo;
|
|
1543
|
+
}
|
|
1544
|
+
get signatureAlgorithm() {
|
|
1545
|
+
const oid = this.signatureAlgorithmObj.subs[0].toOID();
|
|
1546
|
+
const algo = ECDSA_SIGNATURE_ALGOS[oid] || RSA_SIGNATURE_ALGOS[oid];
|
|
1547
|
+
return algo;
|
|
1548
|
+
}
|
|
1549
|
+
get signatureValue() {
|
|
1550
|
+
return this.signatureValueObj.value;
|
|
1551
|
+
}
|
|
1552
|
+
get tstInfo() {
|
|
1553
|
+
return new TSTInfo(this.eContentObj.subs[0].subs[0]);
|
|
1554
|
+
}
|
|
1555
|
+
async verify(data, publicKey) {
|
|
1556
|
+
if (!this.timeStampTokenObj) {
|
|
1557
|
+
throw new RFC3161TimestampVerificationError("timeStampToken is missing");
|
|
1558
|
+
}
|
|
1559
|
+
if (this.contentType !== OID_PKCS9_CONTENT_TYPE_SIGNED_DATA) {
|
|
1560
|
+
throw new RFC3161TimestampVerificationError(`incorrect content type: ${this.contentType}`);
|
|
1561
|
+
}
|
|
1562
|
+
if (this.eContentType !== OID_PKCS9_CONTENT_TYPE_TSTINFO) {
|
|
1563
|
+
throw new RFC3161TimestampVerificationError(`incorrect encapsulated content type: ${this.eContentType}`);
|
|
1564
|
+
}
|
|
1565
|
+
await this.tstInfo.verify(data);
|
|
1566
|
+
await this.verifyMessageDigest();
|
|
1567
|
+
await this.verifySignature(publicKey);
|
|
1568
|
+
}
|
|
1569
|
+
async verifyMessageDigest() {
|
|
1570
|
+
const hashAlg = this.signerDigestAlgorithm;
|
|
1571
|
+
const hashAlgName = hashAlg === "sha256" ? HashAlgorithms.SHA256 : hashAlg === "sha384" ? HashAlgorithms.SHA384 : hashAlg === "sha512" ? HashAlgorithms.SHA512 : hashAlg;
|
|
1572
|
+
const tstInfoDigest = await crypto.subtle.digest(hashAlgName, this.tstInfo.raw);
|
|
1573
|
+
const expectedDigest = this.messageDigestAttributeObj.subs[1].subs[0].value;
|
|
1574
|
+
if (!uint8ArrayEqual(new Uint8Array(tstInfoDigest), expectedDigest)) {
|
|
1575
|
+
throw new RFC3161TimestampVerificationError("signed data does not match tstInfo");
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
async verifySignature(key) {
|
|
1579
|
+
const signedAttrs = this.signedAttrsObj.toDER();
|
|
1580
|
+
signedAttrs[0] = 49;
|
|
1581
|
+
const oid = this.signatureAlgorithmObj.subs[0].toOID();
|
|
1582
|
+
const algo = ECDSA_SIGNATURE_ALGOS[oid] || RSA_SIGNATURE_ALGOS[oid];
|
|
1583
|
+
if (!algo) {
|
|
1584
|
+
throw new RFC3161TimestampVerificationError(`Unsupported signature algorithm OID: ${oid}`);
|
|
1585
|
+
}
|
|
1586
|
+
const verified = await verifySignature(key, signedAttrs, this.signatureValue, algo);
|
|
1587
|
+
if (!verified) {
|
|
1588
|
+
throw new RFC3161TimestampVerificationError("signature verification failed");
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
// https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2
|
|
1592
|
+
get pkiStatusInfoObj() {
|
|
1593
|
+
return this.root.subs[0];
|
|
1594
|
+
}
|
|
1595
|
+
// https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2
|
|
1596
|
+
get timeStampTokenObj() {
|
|
1597
|
+
return this.root.subs[1];
|
|
1598
|
+
}
|
|
1599
|
+
// https://datatracker.ietf.org/doc/html/rfc5652#section-3
|
|
1600
|
+
get contentTypeObj() {
|
|
1601
|
+
return this.timeStampTokenObj.subs[0];
|
|
1602
|
+
}
|
|
1603
|
+
// https://www.rfc-editor.org/rfc/rfc5652#section-3
|
|
1604
|
+
get signedDataObj() {
|
|
1605
|
+
const obj = this.timeStampTokenObj.subs.find((sub) => sub.tag.isContextSpecific(0));
|
|
1606
|
+
if (!obj) {
|
|
1607
|
+
throw new RFC3161TimestampVerificationError("Missing timeStampTokenObj sub.");
|
|
1608
|
+
}
|
|
1609
|
+
return obj.subs[0];
|
|
1610
|
+
}
|
|
1611
|
+
// https://datatracker.ietf.org/doc/html/rfc5652#section-5.1
|
|
1612
|
+
get encapContentInfoObj() {
|
|
1613
|
+
return this.signedDataObj.subs[2];
|
|
1614
|
+
}
|
|
1615
|
+
// https://datatracker.ietf.org/doc/html/rfc5652#section-5.1
|
|
1616
|
+
get signerInfosObj() {
|
|
1617
|
+
const sd = this.signedDataObj;
|
|
1618
|
+
return sd.subs[sd.subs.length - 1];
|
|
1619
|
+
}
|
|
1620
|
+
// https://www.rfc-editor.org/rfc/rfc5652#section-5.1
|
|
1621
|
+
get signerInfoObj() {
|
|
1622
|
+
return this.signerInfosObj.subs[0];
|
|
1623
|
+
}
|
|
1624
|
+
// https://datatracker.ietf.org/doc/html/rfc5652#section-5.2
|
|
1625
|
+
get eContentTypeObj() {
|
|
1626
|
+
return this.encapContentInfoObj.subs[0];
|
|
1627
|
+
}
|
|
1628
|
+
// https://datatracker.ietf.org/doc/html/rfc5652#section-5.2
|
|
1629
|
+
get eContentObj() {
|
|
1630
|
+
return this.encapContentInfoObj.subs[1];
|
|
1631
|
+
}
|
|
1632
|
+
// https://datatracker.ietf.org/doc/html/rfc5652#section-5.3
|
|
1633
|
+
get signedAttrsObj() {
|
|
1634
|
+
const signedAttrs = this.signerInfoObj.subs.find((sub) => sub.tag.isContextSpecific(0));
|
|
1635
|
+
if (!signedAttrs) {
|
|
1636
|
+
throw new RFC3161TimestampVerificationError("Missing signedAttrsObj.");
|
|
1637
|
+
}
|
|
1638
|
+
return signedAttrs;
|
|
1639
|
+
}
|
|
1640
|
+
// https://datatracker.ietf.org/doc/html/rfc5652#section-5.3
|
|
1641
|
+
get messageDigestAttributeObj() {
|
|
1642
|
+
const messageDigest = this.signedAttrsObj.subs.find((sub) => sub.subs[0].tag.isOID() && sub.subs[0].toOID() === OID_PKCS9_MESSAGE_DIGEST_KEY);
|
|
1643
|
+
if (!messageDigest) {
|
|
1644
|
+
throw new RFC3161TimestampVerificationError("Missing messageDigest.");
|
|
1645
|
+
}
|
|
1646
|
+
return messageDigest;
|
|
1647
|
+
}
|
|
1648
|
+
// https://datatracker.ietf.org/doc/html/rfc5652#section-5.3
|
|
1649
|
+
get signerSidObj() {
|
|
1650
|
+
return this.signerInfoObj.subs[1];
|
|
1651
|
+
}
|
|
1652
|
+
// https://datatracker.ietf.org/doc/html/rfc5652#section-5.3
|
|
1653
|
+
get signerDigestAlgorithmObj() {
|
|
1654
|
+
return this.signerInfoObj.subs[2];
|
|
1655
|
+
}
|
|
1656
|
+
// https://datatracker.ietf.org/doc/html/rfc5652#section-5.3
|
|
1657
|
+
get signatureAlgorithmObj() {
|
|
1658
|
+
return this.signerInfoObj.subs[4];
|
|
1659
|
+
}
|
|
1660
|
+
// https://datatracker.ietf.org/doc/html/rfc5652#section-5.3
|
|
1661
|
+
get signatureValueObj() {
|
|
1662
|
+
return this.signerInfoObj.subs[5];
|
|
1663
|
+
}
|
|
1664
|
+
};
|
|
1665
|
+
|
|
1666
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/timestamp/tsa.js
|
|
1667
|
+
async function verifyRFC3161Timestamp(timestamp, data, timestampAuthorities) {
|
|
1668
|
+
const signingTime = timestamp.signingTime;
|
|
1669
|
+
let validAuthorities = filterCertAuthorities(timestampAuthorities, signingTime);
|
|
1670
|
+
validAuthorities = filterCAsBySerialAndIssuer(validAuthorities, {
|
|
1671
|
+
serialNumber: timestamp.signerSerialNumber,
|
|
1672
|
+
issuer: timestamp.signerIssuer
|
|
1673
|
+
});
|
|
1674
|
+
const verificationResults = await Promise.allSettled(validAuthorities.map((ca) => verifyTimestampForCA(timestamp, data, ca)));
|
|
1675
|
+
const verified = verificationResults.some((result) => result.status === "fulfilled");
|
|
1676
|
+
if (!verified) {
|
|
1677
|
+
const errors = verificationResults.filter((r) => r.status === "rejected").map((r) => r.reason?.message || "Unknown error");
|
|
1678
|
+
throw new Error(`Timestamp could not be verified against any trusted authority. Errors: ${errors.join(", ")}`);
|
|
1679
|
+
}
|
|
1680
|
+
return signingTime;
|
|
1681
|
+
}
|
|
1682
|
+
__name(verifyRFC3161Timestamp, "verifyRFC3161Timestamp");
|
|
1683
|
+
function filterCertAuthorities(authorities, validAt) {
|
|
1684
|
+
return authorities.filter((ca) => {
|
|
1685
|
+
if (ca.validFor) {
|
|
1686
|
+
const start = ca.validFor.start ? new Date(ca.validFor.start) : null;
|
|
1687
|
+
const end = ca.validFor.end ? new Date(ca.validFor.end) : null;
|
|
1688
|
+
if (start && validAt < start) {
|
|
1689
|
+
return false;
|
|
1690
|
+
}
|
|
1691
|
+
if (end && validAt > end) {
|
|
1692
|
+
return false;
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
return true;
|
|
1696
|
+
});
|
|
1697
|
+
}
|
|
1698
|
+
__name(filterCertAuthorities, "filterCertAuthorities");
|
|
1699
|
+
function filterCAsBySerialAndIssuer(timestampAuthorities, criteria) {
|
|
1700
|
+
return timestampAuthorities.filter((ca) => {
|
|
1701
|
+
if (!ca.certChain || ca.certChain.certificates.length === 0) {
|
|
1702
|
+
return false;
|
|
1703
|
+
}
|
|
1704
|
+
const leafCert = X509Certificate.parse(base64ToUint8Array(ca.certChain.certificates[0].rawBytes));
|
|
1705
|
+
return uint8ArrayEqual(leafCert.serialNumber, criteria.serialNumber) && uint8ArrayEqual(leafCert.issuer, criteria.issuer);
|
|
1706
|
+
});
|
|
1707
|
+
}
|
|
1708
|
+
__name(filterCAsBySerialAndIssuer, "filterCAsBySerialAndIssuer");
|
|
1709
|
+
async function verifyTimestampForCA(timestamp, data, ca) {
|
|
1710
|
+
if (!ca.certChain || ca.certChain.certificates.length === 0) {
|
|
1711
|
+
throw new Error("Certificate authority missing certificate chain");
|
|
1712
|
+
}
|
|
1713
|
+
const leafCert = X509Certificate.parse(base64ToUint8Array(ca.certChain.certificates[0].rawBytes));
|
|
1714
|
+
const signingTime = timestamp.signingTime;
|
|
1715
|
+
const trustedCerts = ca.certChain.certificates.slice(1).map((cert) => X509Certificate.parse(base64ToUint8Array(cert.rawBytes)));
|
|
1716
|
+
try {
|
|
1717
|
+
const verifier = new CertificateChainVerifier({
|
|
1718
|
+
untrustedCert: leafCert,
|
|
1719
|
+
trustedCerts,
|
|
1720
|
+
timestamp: signingTime
|
|
1721
|
+
});
|
|
1722
|
+
await verifier.verify();
|
|
1723
|
+
} catch (e) {
|
|
1724
|
+
throw new Error(`TSA certificate chain verification failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
1725
|
+
}
|
|
1726
|
+
const publicKey = await leafCert.publicKeyObj;
|
|
1727
|
+
await timestamp.verify(data, publicKey);
|
|
1728
|
+
}
|
|
1729
|
+
__name(verifyTimestampForCA, "verifyTimestampForCA");
|
|
1730
|
+
async function verifyBundleTimestamp(timestampData, signature, timestampAuthorities) {
|
|
1731
|
+
if (!timestampData?.rfc3161Timestamps?.length) {
|
|
1732
|
+
return [];
|
|
1733
|
+
}
|
|
1734
|
+
const verifiedResults = [];
|
|
1735
|
+
for (const tsData of timestampData.rfc3161Timestamps) {
|
|
1736
|
+
const timestampBytes = base64ToUint8Array(tsData.signedTimestamp);
|
|
1737
|
+
const timestamp = RFC3161Timestamp.parse(timestampBytes);
|
|
1738
|
+
const signingTime = await verifyRFC3161Timestamp(timestamp, signature, timestampAuthorities);
|
|
1739
|
+
verifiedResults.push({
|
|
1740
|
+
signingTime,
|
|
1741
|
+
signerSerialNumber: Array.from(timestamp.signerSerialNumber).join(",")
|
|
1742
|
+
});
|
|
1743
|
+
}
|
|
1744
|
+
for (let i = 0; i < verifiedResults.length; i++) {
|
|
1745
|
+
for (let j = i + 1; j < verifiedResults.length; j++) {
|
|
1746
|
+
if (verifiedResults[i].signingTime.getTime() === verifiedResults[j].signingTime.getTime() && verifiedResults[i].signerSerialNumber === verifiedResults[j].signerSerialNumber) {
|
|
1747
|
+
throw new Error("Duplicate TSA timestamp detected");
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
return verifiedResults.map((r) => r.signingTime);
|
|
1752
|
+
}
|
|
1753
|
+
__name(verifyBundleTimestamp, "verifyBundleTimestamp");
|
|
1754
|
+
|
|
1755
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/trust/tuf.js
|
|
1756
|
+
var DEFAULT_CONFIG = {
|
|
1757
|
+
metadataUrl: "https://tuf-repo-cdn.sigstore.dev/",
|
|
1758
|
+
targetBaseUrl: "https://tuf-repo-cdn.sigstore.dev/targets/",
|
|
1759
|
+
namespace: "tuf-cache",
|
|
1760
|
+
trustedRootTarget: "trusted_root.json",
|
|
1761
|
+
cacheTTL: 36e5
|
|
1762
|
+
// 1 hour
|
|
1763
|
+
};
|
|
1764
|
+
var TrustedRootProvider = class {
|
|
1765
|
+
static {
|
|
1766
|
+
__name(this, "TrustedRootProvider");
|
|
1767
|
+
}
|
|
1768
|
+
constructor(options = {}) {
|
|
1769
|
+
const metadataUrl = options.metadataUrl || DEFAULT_CONFIG.metadataUrl;
|
|
1770
|
+
this.metadataUrl = metadataUrl.endsWith("/") ? metadataUrl : `${metadataUrl}/`;
|
|
1771
|
+
const targetBaseUrl = options.targetBaseUrl || DEFAULT_CONFIG.targetBaseUrl;
|
|
1772
|
+
this.targetBaseUrl = targetBaseUrl.endsWith("/") ? targetBaseUrl : `${targetBaseUrl}/`;
|
|
1773
|
+
this.initialRoot = options.initialRoot;
|
|
1774
|
+
this.namespace = options.namespace || DEFAULT_CONFIG.namespace;
|
|
1775
|
+
this.trustedRootTarget = options.trustedRootTarget || DEFAULT_CONFIG.trustedRootTarget;
|
|
1776
|
+
this.cacheTTL = options.cacheTTL ?? DEFAULT_CONFIG.cacheTTL;
|
|
1777
|
+
this.disableCache = options.disableCache ?? false;
|
|
1778
|
+
}
|
|
1779
|
+
/**
|
|
1780
|
+
* Initialize the TUF client
|
|
1781
|
+
* Lazy initialization to avoid loading TUF client until needed
|
|
1782
|
+
*/
|
|
1783
|
+
async initTUFClient() {
|
|
1784
|
+
if (this.tufClient) {
|
|
1785
|
+
return;
|
|
1786
|
+
}
|
|
1787
|
+
try {
|
|
1788
|
+
const { TUFClient } = await import("./c-EUEPIW4S.mjs");
|
|
1789
|
+
const rootMetadata = this.initialRoot || await this.getDefaultRoot();
|
|
1790
|
+
this.tufClient = new TUFClient(this.metadataUrl, rootMetadata, this.namespace, this.targetBaseUrl, { disableCache: this.disableCache });
|
|
1791
|
+
} catch (error) {
|
|
1792
|
+
throw new Error(`Failed to initialize TUF client: ${error instanceof Error ? error.message : String(error)}`);
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
/**
|
|
1796
|
+
* Get the default embedded root metadata
|
|
1797
|
+
* Returns the TUF root.json that bootstraps the TUF client
|
|
1798
|
+
*/
|
|
1799
|
+
async getDefaultRoot() {
|
|
1800
|
+
const { default: tufRootBase64 } = await import("./c-YUSTRATJ.mjs");
|
|
1801
|
+
const decoder = new TextDecoder();
|
|
1802
|
+
const rootBytes = Uint8Array.from(atob(tufRootBase64), (c) => c.charCodeAt(0));
|
|
1803
|
+
return decoder.decode(rootBytes);
|
|
1804
|
+
}
|
|
1805
|
+
/**
|
|
1806
|
+
* Check if cached trusted root is still valid
|
|
1807
|
+
*/
|
|
1808
|
+
isCacheValid() {
|
|
1809
|
+
if (!this.cachedRoot || !this.cacheTimestamp) {
|
|
1810
|
+
return false;
|
|
1811
|
+
}
|
|
1812
|
+
const now = Date.now();
|
|
1813
|
+
return now - this.cacheTimestamp < this.cacheTTL;
|
|
1814
|
+
}
|
|
1815
|
+
/**
|
|
1816
|
+
* Get the Sigstore trusted root metadata
|
|
1817
|
+
* Uses TUF to securely fetch and verify the trusted root
|
|
1818
|
+
*
|
|
1819
|
+
* @returns Promise<TrustedRoot> The verified trusted root metadata
|
|
1820
|
+
* @throws Error if TUF verification fails or root cannot be fetched
|
|
1821
|
+
*/
|
|
1822
|
+
async getTrustedRoot() {
|
|
1823
|
+
if (this.isCacheValid() && this.cachedRoot) {
|
|
1824
|
+
return this.cachedRoot;
|
|
1825
|
+
}
|
|
1826
|
+
await this.initTUFClient();
|
|
1827
|
+
if (!this.tufClient) {
|
|
1828
|
+
throw new Error("TUF client not initialized");
|
|
1829
|
+
}
|
|
1830
|
+
try {
|
|
1831
|
+
await this.tufClient.updateTUF();
|
|
1832
|
+
const trustedRootBuffer = await this.tufClient.getTarget(this.trustedRootTarget);
|
|
1833
|
+
const trustedRootJson = Uint8ArrayToString(new Uint8Array(trustedRootBuffer));
|
|
1834
|
+
const trustedRoot = JSON.parse(trustedRootJson);
|
|
1835
|
+
this.cachedRoot = trustedRoot;
|
|
1836
|
+
this.cacheTimestamp = Date.now();
|
|
1837
|
+
return trustedRoot;
|
|
1838
|
+
} catch (error) {
|
|
1839
|
+
throw new Error(`Failed to fetch trusted root via TUF: ${error instanceof Error ? error.message : String(error)}`);
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
/**
|
|
1843
|
+
* Manually refresh the trusted root from TUF
|
|
1844
|
+
* Bypasses cache and forces a fresh fetch
|
|
1845
|
+
*
|
|
1846
|
+
* @returns Promise<TrustedRoot> The updated trusted root metadata
|
|
1847
|
+
*/
|
|
1848
|
+
async refreshTrustedRoot() {
|
|
1849
|
+
this.cachedRoot = void 0;
|
|
1850
|
+
this.cacheTimestamp = void 0;
|
|
1851
|
+
return await this.getTrustedRoot();
|
|
1852
|
+
}
|
|
1853
|
+
/**
|
|
1854
|
+
* Clear the cached trusted root
|
|
1855
|
+
* Next call to getTrustedRoot() will fetch fresh data
|
|
1856
|
+
*/
|
|
1857
|
+
clearCache() {
|
|
1858
|
+
this.cachedRoot = void 0;
|
|
1859
|
+
this.cacheTimestamp = void 0;
|
|
1860
|
+
}
|
|
1861
|
+
};
|
|
1862
|
+
|
|
1863
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/errors.js
|
|
1864
|
+
var VerificationError = class _VerificationError extends Error {
|
|
1865
|
+
static {
|
|
1866
|
+
__name(this, "VerificationError");
|
|
1867
|
+
}
|
|
1868
|
+
constructor(code, message) {
|
|
1869
|
+
super(message);
|
|
1870
|
+
this.code = code;
|
|
1871
|
+
this.name = "VerificationError";
|
|
1872
|
+
Object.setPrototypeOf(this, _VerificationError.prototype);
|
|
1873
|
+
}
|
|
1874
|
+
};
|
|
1875
|
+
var TimestampError = class _TimestampError extends VerificationError {
|
|
1876
|
+
static {
|
|
1877
|
+
__name(this, "TimestampError");
|
|
1878
|
+
}
|
|
1879
|
+
constructor(message) {
|
|
1880
|
+
super("TIMESTAMP_ERROR", message);
|
|
1881
|
+
this.name = "TimestampError";
|
|
1882
|
+
Object.setPrototypeOf(this, _TimestampError.prototype);
|
|
1883
|
+
}
|
|
1884
|
+
};
|
|
1885
|
+
var CertificateError = class _CertificateError extends VerificationError {
|
|
1886
|
+
static {
|
|
1887
|
+
__name(this, "CertificateError");
|
|
1888
|
+
}
|
|
1889
|
+
constructor(message) {
|
|
1890
|
+
super("CERTIFICATE_ERROR", message);
|
|
1891
|
+
this.name = "CertificateError";
|
|
1892
|
+
Object.setPrototypeOf(this, _CertificateError.prototype);
|
|
1893
|
+
}
|
|
1894
|
+
};
|
|
1895
|
+
var TLogError = class _TLogError extends VerificationError {
|
|
1896
|
+
static {
|
|
1897
|
+
__name(this, "TLogError");
|
|
1898
|
+
}
|
|
1899
|
+
constructor(message) {
|
|
1900
|
+
super("TLOG_ERROR", message);
|
|
1901
|
+
this.name = "TLogError";
|
|
1902
|
+
Object.setPrototypeOf(this, _TLogError.prototype);
|
|
1903
|
+
}
|
|
1904
|
+
};
|
|
1905
|
+
var SignatureError = class _SignatureError extends VerificationError {
|
|
1906
|
+
static {
|
|
1907
|
+
__name(this, "SignatureError");
|
|
1908
|
+
}
|
|
1909
|
+
constructor(message) {
|
|
1910
|
+
super("SIGNATURE_ERROR", message);
|
|
1911
|
+
this.name = "SignatureError";
|
|
1912
|
+
Object.setPrototypeOf(this, _SignatureError.prototype);
|
|
1913
|
+
}
|
|
1914
|
+
};
|
|
1915
|
+
var PolicyError = class _PolicyError extends VerificationError {
|
|
1916
|
+
static {
|
|
1917
|
+
__name(this, "PolicyError");
|
|
1918
|
+
}
|
|
1919
|
+
constructor(message) {
|
|
1920
|
+
super("POLICY_ERROR", message);
|
|
1921
|
+
this.name = "PolicyError";
|
|
1922
|
+
Object.setPrototypeOf(this, _PolicyError.prototype);
|
|
1923
|
+
}
|
|
1924
|
+
};
|
|
1925
|
+
|
|
1926
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/policy.js
|
|
1927
|
+
var GITHUB_OIDC_ISSUER = "https://token.actions.githubusercontent.com";
|
|
1928
|
+
var SingleX509ExtPolicyV1 = class {
|
|
1929
|
+
static {
|
|
1930
|
+
__name(this, "SingleX509ExtPolicyV1");
|
|
1931
|
+
}
|
|
1932
|
+
constructor(value) {
|
|
1933
|
+
this.expectedValue = value;
|
|
1934
|
+
}
|
|
1935
|
+
verify(cert) {
|
|
1936
|
+
const extValue = this.getExtensionValue(cert);
|
|
1937
|
+
if (extValue === void 0) {
|
|
1938
|
+
throw new PolicyError(`Certificate does not contain ${this.name} (${this.oid}) extension`);
|
|
1939
|
+
}
|
|
1940
|
+
if (extValue !== this.expectedValue) {
|
|
1941
|
+
throw new PolicyError(`Certificate's ${this.name} does not match (got '${extValue}', expected '${this.expectedValue}')`);
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
};
|
|
1945
|
+
var SingleX509ExtPolicyV2 = class extends SingleX509ExtPolicyV1 {
|
|
1946
|
+
static {
|
|
1947
|
+
__name(this, "SingleX509ExtPolicyV2");
|
|
1948
|
+
}
|
|
1949
|
+
};
|
|
1950
|
+
var OIDCIssuer = class extends SingleX509ExtPolicyV1 {
|
|
1951
|
+
static {
|
|
1952
|
+
__name(this, "OIDCIssuer");
|
|
1953
|
+
}
|
|
1954
|
+
constructor() {
|
|
1955
|
+
super(...arguments);
|
|
1956
|
+
this.oid = EXTENSION_OID_FULCIO_ISSUER_V1;
|
|
1957
|
+
this.name = "OIDCIssuer";
|
|
1958
|
+
}
|
|
1959
|
+
getExtensionValue(cert) {
|
|
1960
|
+
return cert.extFulcioIssuerV1?.issuer;
|
|
1961
|
+
}
|
|
1962
|
+
};
|
|
1963
|
+
var GitHubWorkflowTrigger = class extends SingleX509ExtPolicyV1 {
|
|
1964
|
+
static {
|
|
1965
|
+
__name(this, "GitHubWorkflowTrigger");
|
|
1966
|
+
}
|
|
1967
|
+
constructor() {
|
|
1968
|
+
super(...arguments);
|
|
1969
|
+
this.oid = EXTENSION_OID_GITHUB_WORKFLOW_TRIGGER;
|
|
1970
|
+
this.name = "GitHubWorkflowTrigger";
|
|
1971
|
+
}
|
|
1972
|
+
getExtensionValue(cert) {
|
|
1973
|
+
return cert.extGitHubWorkflowTrigger?.workflowTrigger;
|
|
1974
|
+
}
|
|
1975
|
+
};
|
|
1976
|
+
var GitHubWorkflowSHA = class extends SingleX509ExtPolicyV1 {
|
|
1977
|
+
static {
|
|
1978
|
+
__name(this, "GitHubWorkflowSHA");
|
|
1979
|
+
}
|
|
1980
|
+
constructor() {
|
|
1981
|
+
super(...arguments);
|
|
1982
|
+
this.oid = EXTENSION_OID_GITHUB_WORKFLOW_SHA;
|
|
1983
|
+
this.name = "GitHubWorkflowSHA";
|
|
1984
|
+
}
|
|
1985
|
+
getExtensionValue(cert) {
|
|
1986
|
+
return cert.extGitHubWorkflowSHA?.workflowSHA;
|
|
1987
|
+
}
|
|
1988
|
+
};
|
|
1989
|
+
var GitHubWorkflowName = class extends SingleX509ExtPolicyV1 {
|
|
1990
|
+
static {
|
|
1991
|
+
__name(this, "GitHubWorkflowName");
|
|
1992
|
+
}
|
|
1993
|
+
constructor() {
|
|
1994
|
+
super(...arguments);
|
|
1995
|
+
this.oid = EXTENSION_OID_GITHUB_WORKFLOW_NAME;
|
|
1996
|
+
this.name = "GitHubWorkflowName";
|
|
1997
|
+
}
|
|
1998
|
+
getExtensionValue(cert) {
|
|
1999
|
+
return cert.extGitHubWorkflowName?.workflowName;
|
|
2000
|
+
}
|
|
2001
|
+
};
|
|
2002
|
+
var GitHubWorkflowRepository = class extends SingleX509ExtPolicyV1 {
|
|
2003
|
+
static {
|
|
2004
|
+
__name(this, "GitHubWorkflowRepository");
|
|
2005
|
+
}
|
|
2006
|
+
constructor() {
|
|
2007
|
+
super(...arguments);
|
|
2008
|
+
this.oid = EXTENSION_OID_GITHUB_WORKFLOW_REPOSITORY;
|
|
2009
|
+
this.name = "GitHubWorkflowRepository";
|
|
2010
|
+
}
|
|
2011
|
+
getExtensionValue(cert) {
|
|
2012
|
+
return cert.extGitHubWorkflowRepository?.workflowRepository;
|
|
2013
|
+
}
|
|
2014
|
+
};
|
|
2015
|
+
var GitHubWorkflowRef = class extends SingleX509ExtPolicyV1 {
|
|
2016
|
+
static {
|
|
2017
|
+
__name(this, "GitHubWorkflowRef");
|
|
2018
|
+
}
|
|
2019
|
+
constructor() {
|
|
2020
|
+
super(...arguments);
|
|
2021
|
+
this.oid = EXTENSION_OID_GITHUB_WORKFLOW_REF;
|
|
2022
|
+
this.name = "GitHubWorkflowRef";
|
|
2023
|
+
}
|
|
2024
|
+
getExtensionValue(cert) {
|
|
2025
|
+
return cert.extGitHubWorkflowRef?.workflowRef;
|
|
2026
|
+
}
|
|
2027
|
+
};
|
|
2028
|
+
var OIDCIssuerV2 = class extends SingleX509ExtPolicyV2 {
|
|
2029
|
+
static {
|
|
2030
|
+
__name(this, "OIDCIssuerV2");
|
|
2031
|
+
}
|
|
2032
|
+
constructor() {
|
|
2033
|
+
super(...arguments);
|
|
2034
|
+
this.oid = EXTENSION_OID_FULCIO_ISSUER_V2;
|
|
2035
|
+
this.name = "OIDCIssuerV2";
|
|
2036
|
+
}
|
|
2037
|
+
getExtensionValue(cert) {
|
|
2038
|
+
return cert.extFulcioIssuerV2?.issuer;
|
|
2039
|
+
}
|
|
2040
|
+
};
|
|
2041
|
+
var OIDCBuildSignerURI = class extends SingleX509ExtPolicyV2 {
|
|
2042
|
+
static {
|
|
2043
|
+
__name(this, "OIDCBuildSignerURI");
|
|
2044
|
+
}
|
|
2045
|
+
constructor() {
|
|
2046
|
+
super(...arguments);
|
|
2047
|
+
this.oid = EXTENSION_OID_BUILD_SIGNER_URI;
|
|
2048
|
+
this.name = "OIDCBuildSignerURI";
|
|
2049
|
+
}
|
|
2050
|
+
getExtensionValue(cert) {
|
|
2051
|
+
return cert.extBuildSignerURI?.buildSignerURI;
|
|
2052
|
+
}
|
|
2053
|
+
};
|
|
2054
|
+
var OIDCBuildSignerDigest = class extends SingleX509ExtPolicyV2 {
|
|
2055
|
+
static {
|
|
2056
|
+
__name(this, "OIDCBuildSignerDigest");
|
|
2057
|
+
}
|
|
2058
|
+
constructor() {
|
|
2059
|
+
super(...arguments);
|
|
2060
|
+
this.oid = EXTENSION_OID_BUILD_SIGNER_DIGEST;
|
|
2061
|
+
this.name = "OIDCBuildSignerDigest";
|
|
2062
|
+
}
|
|
2063
|
+
getExtensionValue(cert) {
|
|
2064
|
+
return cert.extBuildSignerDigest?.buildSignerDigest;
|
|
2065
|
+
}
|
|
2066
|
+
};
|
|
2067
|
+
var OIDCRunnerEnvironment = class extends SingleX509ExtPolicyV2 {
|
|
2068
|
+
static {
|
|
2069
|
+
__name(this, "OIDCRunnerEnvironment");
|
|
2070
|
+
}
|
|
2071
|
+
constructor() {
|
|
2072
|
+
super(...arguments);
|
|
2073
|
+
this.oid = EXTENSION_OID_RUNNER_ENVIRONMENT;
|
|
2074
|
+
this.name = "OIDCRunnerEnvironment";
|
|
2075
|
+
}
|
|
2076
|
+
getExtensionValue(cert) {
|
|
2077
|
+
return cert.extRunnerEnvironment?.runnerEnvironment;
|
|
2078
|
+
}
|
|
2079
|
+
};
|
|
2080
|
+
var OIDCSourceRepositoryURI = class extends SingleX509ExtPolicyV2 {
|
|
2081
|
+
static {
|
|
2082
|
+
__name(this, "OIDCSourceRepositoryURI");
|
|
2083
|
+
}
|
|
2084
|
+
constructor() {
|
|
2085
|
+
super(...arguments);
|
|
2086
|
+
this.oid = EXTENSION_OID_SOURCE_REPOSITORY_URI;
|
|
2087
|
+
this.name = "OIDCSourceRepositoryURI";
|
|
2088
|
+
}
|
|
2089
|
+
getExtensionValue(cert) {
|
|
2090
|
+
return cert.extSourceRepositoryURI?.sourceRepositoryURI;
|
|
2091
|
+
}
|
|
2092
|
+
};
|
|
2093
|
+
var OIDCSourceRepositoryDigest = class extends SingleX509ExtPolicyV2 {
|
|
2094
|
+
static {
|
|
2095
|
+
__name(this, "OIDCSourceRepositoryDigest");
|
|
2096
|
+
}
|
|
2097
|
+
constructor() {
|
|
2098
|
+
super(...arguments);
|
|
2099
|
+
this.oid = EXTENSION_OID_SOURCE_REPOSITORY_DIGEST;
|
|
2100
|
+
this.name = "OIDCSourceRepositoryDigest";
|
|
2101
|
+
}
|
|
2102
|
+
getExtensionValue(cert) {
|
|
2103
|
+
return cert.extSourceRepositoryDigest?.sourceRepositoryDigest;
|
|
2104
|
+
}
|
|
2105
|
+
};
|
|
2106
|
+
var OIDCSourceRepositoryRef = class extends SingleX509ExtPolicyV2 {
|
|
2107
|
+
static {
|
|
2108
|
+
__name(this, "OIDCSourceRepositoryRef");
|
|
2109
|
+
}
|
|
2110
|
+
constructor() {
|
|
2111
|
+
super(...arguments);
|
|
2112
|
+
this.oid = EXTENSION_OID_SOURCE_REPOSITORY_REF;
|
|
2113
|
+
this.name = "OIDCSourceRepositoryRef";
|
|
2114
|
+
}
|
|
2115
|
+
getExtensionValue(cert) {
|
|
2116
|
+
return cert.extSourceRepositoryRef?.sourceRepositoryRef;
|
|
2117
|
+
}
|
|
2118
|
+
};
|
|
2119
|
+
var OIDCSourceRepositoryIdentifier = class extends SingleX509ExtPolicyV2 {
|
|
2120
|
+
static {
|
|
2121
|
+
__name(this, "OIDCSourceRepositoryIdentifier");
|
|
2122
|
+
}
|
|
2123
|
+
constructor() {
|
|
2124
|
+
super(...arguments);
|
|
2125
|
+
this.oid = EXTENSION_OID_SOURCE_REPOSITORY_IDENTIFIER;
|
|
2126
|
+
this.name = "OIDCSourceRepositoryIdentifier";
|
|
2127
|
+
}
|
|
2128
|
+
getExtensionValue(cert) {
|
|
2129
|
+
return cert.extSourceRepositoryIdentifier?.sourceRepositoryIdentifier;
|
|
2130
|
+
}
|
|
2131
|
+
};
|
|
2132
|
+
var OIDCSourceRepositoryOwnerURI = class extends SingleX509ExtPolicyV2 {
|
|
2133
|
+
static {
|
|
2134
|
+
__name(this, "OIDCSourceRepositoryOwnerURI");
|
|
2135
|
+
}
|
|
2136
|
+
constructor() {
|
|
2137
|
+
super(...arguments);
|
|
2138
|
+
this.oid = EXTENSION_OID_SOURCE_REPOSITORY_OWNER_URI;
|
|
2139
|
+
this.name = "OIDCSourceRepositoryOwnerURI";
|
|
2140
|
+
}
|
|
2141
|
+
getExtensionValue(cert) {
|
|
2142
|
+
return cert.extSourceRepositoryOwnerURI?.sourceRepositoryOwnerURI;
|
|
2143
|
+
}
|
|
2144
|
+
};
|
|
2145
|
+
var OIDCSourceRepositoryOwnerIdentifier = class extends SingleX509ExtPolicyV2 {
|
|
2146
|
+
static {
|
|
2147
|
+
__name(this, "OIDCSourceRepositoryOwnerIdentifier");
|
|
2148
|
+
}
|
|
2149
|
+
constructor() {
|
|
2150
|
+
super(...arguments);
|
|
2151
|
+
this.oid = EXTENSION_OID_SOURCE_REPOSITORY_OWNER_IDENTIFIER;
|
|
2152
|
+
this.name = "OIDCSourceRepositoryOwnerIdentifier";
|
|
2153
|
+
}
|
|
2154
|
+
getExtensionValue(cert) {
|
|
2155
|
+
return cert.extSourceRepositoryOwnerIdentifier?.sourceRepositoryOwnerIdentifier;
|
|
2156
|
+
}
|
|
2157
|
+
};
|
|
2158
|
+
var OIDCBuildConfigURI = class extends SingleX509ExtPolicyV2 {
|
|
2159
|
+
static {
|
|
2160
|
+
__name(this, "OIDCBuildConfigURI");
|
|
2161
|
+
}
|
|
2162
|
+
constructor() {
|
|
2163
|
+
super(...arguments);
|
|
2164
|
+
this.oid = EXTENSION_OID_BUILD_CONFIG_URI;
|
|
2165
|
+
this.name = "OIDCBuildConfigURI";
|
|
2166
|
+
}
|
|
2167
|
+
getExtensionValue(cert) {
|
|
2168
|
+
return cert.extBuildConfigURI?.buildConfigURI;
|
|
2169
|
+
}
|
|
2170
|
+
};
|
|
2171
|
+
var OIDCBuildConfigDigest = class extends SingleX509ExtPolicyV2 {
|
|
2172
|
+
static {
|
|
2173
|
+
__name(this, "OIDCBuildConfigDigest");
|
|
2174
|
+
}
|
|
2175
|
+
constructor() {
|
|
2176
|
+
super(...arguments);
|
|
2177
|
+
this.oid = EXTENSION_OID_BUILD_CONFIG_DIGEST;
|
|
2178
|
+
this.name = "OIDCBuildConfigDigest";
|
|
2179
|
+
}
|
|
2180
|
+
getExtensionValue(cert) {
|
|
2181
|
+
return cert.extBuildConfigDigest?.buildConfigDigest;
|
|
2182
|
+
}
|
|
2183
|
+
};
|
|
2184
|
+
var OIDCBuildTrigger = class extends SingleX509ExtPolicyV2 {
|
|
2185
|
+
static {
|
|
2186
|
+
__name(this, "OIDCBuildTrigger");
|
|
2187
|
+
}
|
|
2188
|
+
constructor() {
|
|
2189
|
+
super(...arguments);
|
|
2190
|
+
this.oid = EXTENSION_OID_BUILD_TRIGGER;
|
|
2191
|
+
this.name = "OIDCBuildTrigger";
|
|
2192
|
+
}
|
|
2193
|
+
getExtensionValue(cert) {
|
|
2194
|
+
return cert.extBuildTrigger?.buildTrigger;
|
|
2195
|
+
}
|
|
2196
|
+
};
|
|
2197
|
+
var OIDCRunInvocationURI = class extends SingleX509ExtPolicyV2 {
|
|
2198
|
+
static {
|
|
2199
|
+
__name(this, "OIDCRunInvocationURI");
|
|
2200
|
+
}
|
|
2201
|
+
constructor() {
|
|
2202
|
+
super(...arguments);
|
|
2203
|
+
this.oid = EXTENSION_OID_RUN_INVOCATION_URI;
|
|
2204
|
+
this.name = "OIDCRunInvocationURI";
|
|
2205
|
+
}
|
|
2206
|
+
getExtensionValue(cert) {
|
|
2207
|
+
return cert.extRunInvocationURI?.runInvocationURI;
|
|
2208
|
+
}
|
|
2209
|
+
};
|
|
2210
|
+
var OIDCSourceRepositoryVisibility = class extends SingleX509ExtPolicyV2 {
|
|
2211
|
+
static {
|
|
2212
|
+
__name(this, "OIDCSourceRepositoryVisibility");
|
|
2213
|
+
}
|
|
2214
|
+
constructor() {
|
|
2215
|
+
super(...arguments);
|
|
2216
|
+
this.oid = EXTENSION_OID_SOURCE_REPOSITORY_VISIBILITY;
|
|
2217
|
+
this.name = "OIDCSourceRepositoryVisibility";
|
|
2218
|
+
}
|
|
2219
|
+
getExtensionValue(cert) {
|
|
2220
|
+
return cert.extSourceRepositoryVisibility?.sourceRepositoryVisibility;
|
|
2221
|
+
}
|
|
2222
|
+
};
|
|
2223
|
+
var AnyOf = class {
|
|
2224
|
+
static {
|
|
2225
|
+
__name(this, "AnyOf");
|
|
2226
|
+
}
|
|
2227
|
+
constructor(children) {
|
|
2228
|
+
this.children = children;
|
|
2229
|
+
}
|
|
2230
|
+
verify(cert) {
|
|
2231
|
+
for (const child of this.children) {
|
|
2232
|
+
try {
|
|
2233
|
+
child.verify(cert);
|
|
2234
|
+
return;
|
|
2235
|
+
} catch {
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
throw new PolicyError(`0 of ${this.children.length} policies succeeded`);
|
|
2239
|
+
}
|
|
2240
|
+
};
|
|
2241
|
+
var AllOf = class {
|
|
2242
|
+
static {
|
|
2243
|
+
__name(this, "AllOf");
|
|
2244
|
+
}
|
|
2245
|
+
constructor(children) {
|
|
2246
|
+
this.children = children;
|
|
2247
|
+
}
|
|
2248
|
+
verify(cert) {
|
|
2249
|
+
if (this.children.length < 1) {
|
|
2250
|
+
throw new PolicyError("no child policies to verify");
|
|
2251
|
+
}
|
|
2252
|
+
for (const child of this.children) {
|
|
2253
|
+
child.verify(cert);
|
|
2254
|
+
}
|
|
2255
|
+
}
|
|
2256
|
+
};
|
|
2257
|
+
var Identity = class {
|
|
2258
|
+
static {
|
|
2259
|
+
__name(this, "Identity");
|
|
2260
|
+
}
|
|
2261
|
+
constructor(options) {
|
|
2262
|
+
this.identity = options.identity;
|
|
2263
|
+
this.issuerPolicy = options.issuer ? new OIDCIssuer(options.issuer) : null;
|
|
2264
|
+
}
|
|
2265
|
+
verify(cert) {
|
|
2266
|
+
if (this.issuerPolicy) {
|
|
2267
|
+
this.issuerPolicy.verify(cert);
|
|
2268
|
+
}
|
|
2269
|
+
const sanExt = cert.extSubjectAltName;
|
|
2270
|
+
if (!sanExt) {
|
|
2271
|
+
throw new PolicyError("Certificate does not contain SubjectAlternativeName extension");
|
|
2272
|
+
}
|
|
2273
|
+
const allSans = /* @__PURE__ */ new Set();
|
|
2274
|
+
if (sanExt.rfc822Name) {
|
|
2275
|
+
allSans.add(sanExt.rfc822Name);
|
|
2276
|
+
}
|
|
2277
|
+
if (sanExt.uri) {
|
|
2278
|
+
allSans.add(sanExt.uri);
|
|
2279
|
+
}
|
|
2280
|
+
const otherName = sanExt.otherName(EXTENSION_OID_OTHERNAME);
|
|
2281
|
+
if (otherName) {
|
|
2282
|
+
allSans.add(otherName);
|
|
2283
|
+
}
|
|
2284
|
+
if (!allSans.has(this.identity)) {
|
|
2285
|
+
throw new PolicyError(`Certificate's SANs do not match ${this.identity}; actual SANs: ${Array.from(allSans).join(", ")}`);
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
};
|
|
2289
|
+
|
|
2290
|
+
// node_modules/@freedomofpress/sigstore-browser/dist/sigstore.js
|
|
2291
|
+
var MEDIA_TYPE_BASE = "application/vnd.dev.sigstore.bundle";
|
|
2292
|
+
function getBundleVersion(mediaType) {
|
|
2293
|
+
switch (mediaType) {
|
|
2294
|
+
case `${MEDIA_TYPE_BASE}+json;version=0.1`:
|
|
2295
|
+
return "0.1";
|
|
2296
|
+
case `${MEDIA_TYPE_BASE}+json;version=0.2`:
|
|
2297
|
+
return "0.2";
|
|
2298
|
+
case `${MEDIA_TYPE_BASE}+json;version=0.3`:
|
|
2299
|
+
return "0.3";
|
|
2300
|
+
}
|
|
2301
|
+
if (mediaType.startsWith(`${MEDIA_TYPE_BASE}.v`) && mediaType.endsWith("+json")) {
|
|
2302
|
+
const version = mediaType.replace(`${MEDIA_TYPE_BASE}.v`, "").replace("+json", "");
|
|
2303
|
+
if (/^\d+\.\d+(\.\d+)?$/.test(version)) {
|
|
2304
|
+
return version;
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2307
|
+
return "0.1";
|
|
2308
|
+
}
|
|
2309
|
+
__name(getBundleVersion, "getBundleVersion");
|
|
2310
|
+
function assertRekorV2Timestamp(timestampData) {
|
|
2311
|
+
if (!timestampData?.rfc3161Timestamps?.length) {
|
|
2312
|
+
throw new Error("Rekor v2 bundles require a timestamp for verification.");
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
__name(assertRekorV2Timestamp, "assertRekorV2Timestamp");
|
|
2316
|
+
var SigstoreVerifier = class {
|
|
2317
|
+
static {
|
|
2318
|
+
__name(this, "SigstoreVerifier");
|
|
2319
|
+
}
|
|
2320
|
+
constructor(options = {}) {
|
|
2321
|
+
this.root = void 0;
|
|
2322
|
+
this.rawRoot = void 0;
|
|
2323
|
+
this.options = {
|
|
2324
|
+
tlogThreshold: options.tlogThreshold ?? 1,
|
|
2325
|
+
ctlogThreshold: options.ctlogThreshold ?? 1,
|
|
2326
|
+
tsaThreshold: options.tsaThreshold ?? 0
|
|
2327
|
+
};
|
|
2328
|
+
}
|
|
2329
|
+
async loadLog(frozenTimestamp, logs) {
|
|
2330
|
+
for (const log of logs) {
|
|
2331
|
+
if (frozenTimestamp > new Date(log.publicKey.validFor.start) && (!log.publicKey.validFor.end || new Date(log.publicKey.validFor.end) > frozenTimestamp)) {
|
|
2332
|
+
return {
|
|
2333
|
+
publicKey: await importKey(log.publicKey.keyDetails, log.publicKey.keyDetails, log.publicKey.rawBytes),
|
|
2334
|
+
logId: base64ToUint8Array(log.logId.keyId)
|
|
2335
|
+
};
|
|
2336
|
+
}
|
|
2337
|
+
}
|
|
2338
|
+
return void 0;
|
|
2339
|
+
}
|
|
2340
|
+
async loadCTLogs(frozenTimestamp, ctlogs) {
|
|
2341
|
+
const result = [];
|
|
2342
|
+
for (const log of ctlogs) {
|
|
2343
|
+
const start = new Date(log.publicKey.validFor.start);
|
|
2344
|
+
const end = log.publicKey.validFor.end ? new Date(log.publicKey.validFor.end) : /* @__PURE__ */ new Date("9999-12-31");
|
|
2345
|
+
if (start <= frozenTimestamp) {
|
|
2346
|
+
const publicKey = await importKey(log.publicKey.keyDetails, log.publicKey.keyDetails, log.publicKey.rawBytes);
|
|
2347
|
+
result.push({
|
|
2348
|
+
logID: base64ToUint8Array(log.logId.keyId),
|
|
2349
|
+
publicKey,
|
|
2350
|
+
validFor: { start, end }
|
|
2351
|
+
});
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
if (result.length === 0) {
|
|
2355
|
+
throw new Error("Could not find any valid CT logs in sigstore root.");
|
|
2356
|
+
}
|
|
2357
|
+
return result;
|
|
2358
|
+
}
|
|
2359
|
+
// Adapted from https://github.com/sigstore/sigstore-js/blob/main/packages/verify/src/key/certificate.ts#L22-L53
|
|
2360
|
+
// Verifies that the leaf certificate chains to a trusted CA and is valid at the given timestamp.
|
|
2361
|
+
// Differences from sigstore-js:
|
|
2362
|
+
// - This is async (uses await) because our CertificateChainVerifier.verify() is async
|
|
2363
|
+
// - sigstore-js filters CAs using filterCertAuthorities() before calling this function,
|
|
2364
|
+
// we do the timestamp filtering inline within this function
|
|
2365
|
+
async verifyCertificateChain(timestamp, leaf, certificateAuthorities) {
|
|
2366
|
+
let lastError;
|
|
2367
|
+
for (const ca of certificateAuthorities) {
|
|
2368
|
+
if (timestamp < ca.validFor.start || timestamp > ca.validFor.end) {
|
|
2369
|
+
continue;
|
|
2370
|
+
}
|
|
2371
|
+
try {
|
|
2372
|
+
const verifier = new CertificateChainVerifier({
|
|
2373
|
+
trustedCerts: ca.certChain,
|
|
2374
|
+
untrustedCert: leaf,
|
|
2375
|
+
timestamp
|
|
2376
|
+
});
|
|
2377
|
+
return await verifier.verify();
|
|
2378
|
+
} catch (err) {
|
|
2379
|
+
lastError = err;
|
|
2380
|
+
}
|
|
2381
|
+
}
|
|
2382
|
+
throw new Error(`Failed to verify certificate chain: ${lastError?.message || "No valid CAs found"}`);
|
|
2383
|
+
}
|
|
2384
|
+
// Load timestamp authorities that are valid at the frozen timestamp.
|
|
2385
|
+
// Unlike sigstore-js which doesn't pre-load TSAs (it passes raw TSA data to timestamp verification),
|
|
2386
|
+
// we parse and filter them at initialization time for consistency with how we handle CAs and other roots.
|
|
2387
|
+
loadTSA(frozenTimestamp, tsas) {
|
|
2388
|
+
if (!tsas || tsas.length === 0) {
|
|
2389
|
+
return [];
|
|
2390
|
+
}
|
|
2391
|
+
const result = [];
|
|
2392
|
+
for (const tsa of tsas) {
|
|
2393
|
+
const start = new Date(tsa.validFor.start);
|
|
2394
|
+
const end = tsa.validFor.end ? new Date(tsa.validFor.end) : /* @__PURE__ */ new Date(864e13);
|
|
2395
|
+
if (frozenTimestamp > start && frozenTimestamp < end) {
|
|
2396
|
+
const certChain = tsa.certChain.certificates.map((cert) => X509Certificate.parse(base64ToUint8Array(cert.rawBytes)));
|
|
2397
|
+
if (certChain.length > 0) {
|
|
2398
|
+
result.push({
|
|
2399
|
+
certChain,
|
|
2400
|
+
validFor: { start, end }
|
|
2401
|
+
});
|
|
2402
|
+
}
|
|
2403
|
+
}
|
|
2404
|
+
}
|
|
2405
|
+
return result;
|
|
2406
|
+
}
|
|
2407
|
+
// Load certificate authorities (Fulcio CAs) that are valid at the frozen timestamp.
|
|
2408
|
+
// Similar to sigstore-js's filterCertAuthorities() in trust/filter.ts, but we also
|
|
2409
|
+
// parse the certificates at load time whereas sigstore-js keeps them in the trust material
|
|
2410
|
+
// and parses them during verification. This pre-loading approach is consistent with our
|
|
2411
|
+
// architecture of loading all trusted roots at initialization.
|
|
2412
|
+
loadCA(frozenTimestamp, cas) {
|
|
2413
|
+
const result = [];
|
|
2414
|
+
for (const ca of cas) {
|
|
2415
|
+
const start = new Date(ca.validFor.start);
|
|
2416
|
+
const end = ca.validFor.end ? new Date(ca.validFor.end) : /* @__PURE__ */ new Date(864e13);
|
|
2417
|
+
if (frozenTimestamp > start && frozenTimestamp < end) {
|
|
2418
|
+
const certChain = ca.certChain.certificates.map((cert) => X509Certificate.parse(base64ToUint8Array(cert.rawBytes)));
|
|
2419
|
+
if (certChain.length > 0) {
|
|
2420
|
+
result.push({
|
|
2421
|
+
certChain,
|
|
2422
|
+
validFor: { start, end }
|
|
2423
|
+
});
|
|
2424
|
+
}
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
return result;
|
|
2428
|
+
}
|
|
2429
|
+
async loadSigstoreRoot(rawRoot) {
|
|
2430
|
+
const frozenTimestamp = /* @__PURE__ */ new Date();
|
|
2431
|
+
this.rawRoot = rawRoot;
|
|
2432
|
+
this.root = {
|
|
2433
|
+
rekor: await this.loadLog(frozenTimestamp, rawRoot[SigstoreRoots.tlogs]),
|
|
2434
|
+
ctlogs: await this.loadCTLogs(frozenTimestamp, rawRoot[SigstoreRoots.ctlogs]),
|
|
2435
|
+
certificateAuthorities: this.loadCA(frozenTimestamp, rawRoot[SigstoreRoots.certificateAuthorities]),
|
|
2436
|
+
timestampAuthorities: this.loadTSA(frozenTimestamp, rawRoot.timestampAuthorities)
|
|
2437
|
+
};
|
|
2438
|
+
}
|
|
2439
|
+
/**
|
|
2440
|
+
* Load Sigstore trusted root via TUF
|
|
2441
|
+
* Uses The Update Framework for secure, verified updates of trusted root metadata
|
|
2442
|
+
*
|
|
2443
|
+
* @param tufProvider Optional TrustedRootProvider instance. If not provided, uses default Sigstore TUF repository
|
|
2444
|
+
*/
|
|
2445
|
+
async loadSigstoreRootWithTUF(tufProvider) {
|
|
2446
|
+
const provider = tufProvider || new TrustedRootProvider();
|
|
2447
|
+
const trustedRoot = await provider.getTrustedRoot();
|
|
2448
|
+
await this.loadSigstoreRoot(trustedRoot);
|
|
2449
|
+
}
|
|
2450
|
+
// Adapted from https://github.com/sigstore/sigstore-js/blob/main/packages/verify/src/key/sct.ts
|
|
2451
|
+
// Key differences:
|
|
2452
|
+
// - Adds duplicate SCT detection (not in reference)
|
|
2453
|
+
// - Inline CT log filtering by logID and validity period (reference uses filterTLogAuthorities)
|
|
2454
|
+
// - Returns array of verified SCT logIDs for threshold checking (matches reference behavior)
|
|
2455
|
+
async verifySCT(cert, issuer, ctlogs) {
|
|
2456
|
+
let extSCT;
|
|
2457
|
+
const clone = cert.clone();
|
|
2458
|
+
for (let i = 0; i < clone.extensions.length; i++) {
|
|
2459
|
+
const ext = clone.extensions[i];
|
|
2460
|
+
if (ext.subs[0].toOID() === EXTENSION_OID_SCT) {
|
|
2461
|
+
extSCT = new X509SCTExtension(ext);
|
|
2462
|
+
clone.extensions.splice(i, 1);
|
|
2463
|
+
break;
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2466
|
+
if (!extSCT) {
|
|
2467
|
+
throw new Error("Certificate is missing required SCT extension");
|
|
2468
|
+
}
|
|
2469
|
+
if (extSCT.signedCertificateTimestamps.length === 0) {
|
|
2470
|
+
throw new Error("SCT extension is present but contains no SCTs");
|
|
2471
|
+
}
|
|
2472
|
+
const seenLogIds = /* @__PURE__ */ new Set();
|
|
2473
|
+
for (const sct of extSCT.signedCertificateTimestamps) {
|
|
2474
|
+
const logIdHex = Uint8ArrayToHex(sct.logID);
|
|
2475
|
+
if (seenLogIds.has(logIdHex)) {
|
|
2476
|
+
throw new Error(`Duplicate SCT found for log ID: ${logIdHex}`);
|
|
2477
|
+
}
|
|
2478
|
+
seenLogIds.add(logIdHex);
|
|
2479
|
+
}
|
|
2480
|
+
const preCert = new ByteStream();
|
|
2481
|
+
const issuerId = new Uint8Array(await crypto.subtle.digest(HashAlgorithms.SHA256, issuer.publicKey));
|
|
2482
|
+
preCert.appendView(issuerId);
|
|
2483
|
+
const tbs = clone.tbsCertificate.toDER();
|
|
2484
|
+
preCert.appendUint24(tbs.length);
|
|
2485
|
+
preCert.appendView(tbs);
|
|
2486
|
+
const verifiedSCTs = [];
|
|
2487
|
+
for (const sct of extSCT.signedCertificateTimestamps) {
|
|
2488
|
+
const validCTLogs = ctlogs.filter((log) => {
|
|
2489
|
+
if (!uint8ArrayEqual(log.logID, sct.logID))
|
|
2490
|
+
return false;
|
|
2491
|
+
return log.validFor.start <= sct.datetime && sct.datetime <= log.validFor.end;
|
|
2492
|
+
});
|
|
2493
|
+
const verified = await (async () => {
|
|
2494
|
+
for (const log of validCTLogs) {
|
|
2495
|
+
try {
|
|
2496
|
+
if (await sct.verify(preCert.buffer, log.publicKey)) {
|
|
2497
|
+
return true;
|
|
2498
|
+
}
|
|
2499
|
+
} catch {
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
return false;
|
|
2503
|
+
})();
|
|
2504
|
+
if (!verified) {
|
|
2505
|
+
throw new Error("SCT verification failed");
|
|
2506
|
+
}
|
|
2507
|
+
verifiedSCTs.push(sct.logID);
|
|
2508
|
+
}
|
|
2509
|
+
return verifiedSCTs;
|
|
2510
|
+
}
|
|
2511
|
+
async verifyInclusionPromise(cert, bundle, rekor) {
|
|
2512
|
+
const entries = bundle.verificationMaterial.tlogEntries;
|
|
2513
|
+
if (entries.length < this.options.tlogThreshold) {
|
|
2514
|
+
throw new Error(`Not enough tlog entries: ${entries.length} < ${this.options.tlogThreshold}`);
|
|
2515
|
+
}
|
|
2516
|
+
const MAX_TLOG_ENTRIES = 32;
|
|
2517
|
+
if (entries.length > MAX_TLOG_ENTRIES) {
|
|
2518
|
+
throw new Error(`Too many tlog entries: ${entries.length} > ${MAX_TLOG_ENTRIES}`);
|
|
2519
|
+
}
|
|
2520
|
+
for (let i = 0; i < entries.length; i++) {
|
|
2521
|
+
for (let j = i + 1; j < entries.length; j++) {
|
|
2522
|
+
const iLogId = Uint8ArrayToHex(base64ToUint8Array(entries[i].logId.keyId));
|
|
2523
|
+
const jLogId = Uint8ArrayToHex(base64ToUint8Array(entries[j].logId.keyId));
|
|
2524
|
+
if (iLogId === jLogId && entries[i].logIndex === entries[j].logIndex) {
|
|
2525
|
+
throw new Error(`Duplicate tlog entry found: logID=${iLogId}, logIndex=${entries[i].logIndex}`);
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
const entry = entries[0];
|
|
2530
|
+
const bundleVersion = getBundleVersion(bundle.mediaType);
|
|
2531
|
+
const isV02OrLater = parseFloat(bundleVersion) >= 0.2;
|
|
2532
|
+
if (isV02OrLater && !entry.inclusionProof) {
|
|
2533
|
+
throw new Error("Bundle v0.2+ requires an inclusion proof.");
|
|
2534
|
+
}
|
|
2535
|
+
if (!entry.inclusionPromise?.signedEntryTimestamp) {
|
|
2536
|
+
if (!entry.inclusionProof) {
|
|
2537
|
+
throw new Error("Bundle must have either an inclusion promise or an inclusion proof.");
|
|
2538
|
+
}
|
|
2539
|
+
} else {
|
|
2540
|
+
if (!rekor && entry.inclusionProof) {
|
|
2541
|
+
} else {
|
|
2542
|
+
if (!rekor) {
|
|
2543
|
+
throw new Error("Rekor public key not found in trusted root");
|
|
2544
|
+
}
|
|
2545
|
+
const entryLogId = base64ToUint8Array(entry.logId.keyId);
|
|
2546
|
+
if (!uint8ArrayEqual(rekor.logId, entryLogId)) {
|
|
2547
|
+
throw new Error(`Rekor log ID mismatch: bundle uses ${Uint8ArrayToHex(entryLogId)} but loaded key is for ${Uint8ArrayToHex(rekor.logId)}`);
|
|
2548
|
+
}
|
|
2549
|
+
const signature = base64ToUint8Array(entry.inclusionPromise.signedEntryTimestamp);
|
|
2550
|
+
const keyId = Uint8ArrayToHex(entryLogId);
|
|
2551
|
+
const integratedTime = Number(entry.integratedTime);
|
|
2552
|
+
const signed = stringToUint8Array(canonicalize({
|
|
2553
|
+
body: entry.canonicalizedBody,
|
|
2554
|
+
integratedTime,
|
|
2555
|
+
logIndex: Number(entry.logIndex),
|
|
2556
|
+
logID: keyId
|
|
2557
|
+
}));
|
|
2558
|
+
if (!await verifySignature(rekor.publicKey, signed, signature)) {
|
|
2559
|
+
throw new Error("Failed to verify the inclusion promise in the provided bundle.");
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
if (entry.integratedTime) {
|
|
2564
|
+
const integratedTime = Number(entry.integratedTime);
|
|
2565
|
+
const integratedDate = new Date(integratedTime * 1e3);
|
|
2566
|
+
if (!cert.validForDate(integratedDate)) {
|
|
2567
|
+
throw new Error("Artifact signing was logged outside of the certificate validity.");
|
|
2568
|
+
}
|
|
2569
|
+
} else {
|
|
2570
|
+
assertRekorV2Timestamp(bundle.verificationMaterial.timestampVerificationData);
|
|
2571
|
+
}
|
|
2572
|
+
const bodyJson = JSON.parse(Uint8ArrayToString(base64ToUint8Array(entry.canonicalizedBody)));
|
|
2573
|
+
if (bodyJson.kind === "hashedrekord") {
|
|
2574
|
+
let loggedCertContent;
|
|
2575
|
+
if (bodyJson.spec.hashedRekordV002) {
|
|
2576
|
+
const verifier = bodyJson.spec.hashedRekordV002.signature.verifier;
|
|
2577
|
+
if (verifier?.x509Certificate) {
|
|
2578
|
+
loggedCertContent = verifier.x509Certificate.rawBytes;
|
|
2579
|
+
}
|
|
2580
|
+
} else if (bodyJson.spec.signature?.publicKey) {
|
|
2581
|
+
loggedCertContent = bodyJson.spec.signature.publicKey.content;
|
|
2582
|
+
}
|
|
2583
|
+
if (loggedCertContent) {
|
|
2584
|
+
let loggedCert;
|
|
2585
|
+
if (bodyJson.spec.hashedRekordV002) {
|
|
2586
|
+
loggedCert = X509Certificate.parse(base64ToUint8Array(loggedCertContent));
|
|
2587
|
+
} else {
|
|
2588
|
+
const pemString = Uint8ArrayToString(base64ToUint8Array(loggedCertContent));
|
|
2589
|
+
loggedCert = X509Certificate.parse(pemString);
|
|
2590
|
+
}
|
|
2591
|
+
if (!cert.equals(loggedCert)) {
|
|
2592
|
+
throw new Error("Certificate in Rekor log does not match the signing certificate.");
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
} else if (bodyJson.kind === "dsse") {
|
|
2596
|
+
const verifierContent = bodyJson.spec.signatures?.[0]?.verifier;
|
|
2597
|
+
if (verifierContent) {
|
|
2598
|
+
const pemString = Uint8ArrayToString(base64ToUint8Array(verifierContent));
|
|
2599
|
+
const loggedCert = X509Certificate.parse(pemString);
|
|
2600
|
+
if (!cert.equals(loggedCert)) {
|
|
2601
|
+
throw new Error("Certificate in DSSE tlog entry does not match the signing certificate.");
|
|
2602
|
+
}
|
|
2603
|
+
}
|
|
2604
|
+
} else if (bodyJson.kind === "intoto") {
|
|
2605
|
+
const publicKeyContent = bodyJson.spec.content?.envelope?.signatures?.[0]?.publicKey;
|
|
2606
|
+
if (publicKeyContent) {
|
|
2607
|
+
const pemString = Uint8ArrayToString(base64ToUint8Array(publicKeyContent));
|
|
2608
|
+
const loggedCert = X509Certificate.parse(pemString);
|
|
2609
|
+
if (!cert.equals(loggedCert)) {
|
|
2610
|
+
throw new Error("Certificate in intoto tlog entry does not match the signing certificate.");
|
|
2611
|
+
}
|
|
2612
|
+
}
|
|
2613
|
+
} else {
|
|
2614
|
+
throw new Error(`Unsupported tlog entry kind: ${bodyJson.kind}`);
|
|
2615
|
+
}
|
|
2616
|
+
return true;
|
|
2617
|
+
}
|
|
2618
|
+
async verifyInclusionProof(bundle) {
|
|
2619
|
+
if (!this.rawRoot) {
|
|
2620
|
+
throw new Error("Sigstore root is undefined");
|
|
2621
|
+
}
|
|
2622
|
+
if (bundle.verificationMaterial.tlogEntries.length < 1) {
|
|
2623
|
+
throw new Error("No transparency log entries found in bundle");
|
|
2624
|
+
}
|
|
2625
|
+
for (const entry of bundle.verificationMaterial.tlogEntries) {
|
|
2626
|
+
if (entry.inclusionProof) {
|
|
2627
|
+
await verifyMerkleInclusion(entry);
|
|
2628
|
+
if (entry.inclusionProof.checkpoint) {
|
|
2629
|
+
await verifyCheckpoint(entry, this.rawRoot.tlogs);
|
|
2630
|
+
}
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
async verifyArtifactPolicy(policy, bundle, data, isDigestOnly = false) {
|
|
2635
|
+
if (!this.root) {
|
|
2636
|
+
throw new Error("Sigstore root is undefined");
|
|
2637
|
+
}
|
|
2638
|
+
const cert = bundle.verificationMaterial.certificate || bundle.verificationMaterial.x509CertificateChain?.certificates[0];
|
|
2639
|
+
if (!cert) {
|
|
2640
|
+
throw new Error("No certificate found in bundle");
|
|
2641
|
+
}
|
|
2642
|
+
const signingCert = X509Certificate.parse(base64ToUint8Array(cert.rawBytes));
|
|
2643
|
+
let signature;
|
|
2644
|
+
if (bundle.messageSignature) {
|
|
2645
|
+
signature = base64ToUint8Array(bundle.messageSignature.signature);
|
|
2646
|
+
} else if (bundle.dsseEnvelope) {
|
|
2647
|
+
if (!bundle.dsseEnvelope.signatures || bundle.dsseEnvelope.signatures.length === 0) {
|
|
2648
|
+
throw new Error("DSSE envelope has no signatures");
|
|
2649
|
+
}
|
|
2650
|
+
signature = base64ToUint8Array(bundle.dsseEnvelope.signatures[0].sig);
|
|
2651
|
+
} else {
|
|
2652
|
+
throw new Error("Bundle does not contain a message signature or DSSE envelope");
|
|
2653
|
+
}
|
|
2654
|
+
policy.verify(signingCert);
|
|
2655
|
+
const certPath = await this.verifyCertificateChain(signingCert.notBefore, signingCert, this.root.certificateAuthorities);
|
|
2656
|
+
const issuerCert = certPath.length > 1 ? certPath[1] : certPath[0];
|
|
2657
|
+
const verifiedSCTs = await this.verifySCT(signingCert, issuerCert, this.root.ctlogs);
|
|
2658
|
+
if (verifiedSCTs.length < this.options.ctlogThreshold) {
|
|
2659
|
+
throw new Error(`Not enough valid SCTs: found ${verifiedSCTs.length}, required ${this.options.ctlogThreshold}`);
|
|
2660
|
+
}
|
|
2661
|
+
if (!await this.verifyInclusionPromise(signingCert, bundle, this.root.rekor)) {
|
|
2662
|
+
throw new Error("Inclusion promise validation failed.");
|
|
2663
|
+
}
|
|
2664
|
+
await this.verifyInclusionProof(bundle);
|
|
2665
|
+
for (const entry of bundle.verificationMaterial.tlogEntries) {
|
|
2666
|
+
await verifyTLogBody(entry, bundle);
|
|
2667
|
+
}
|
|
2668
|
+
const verifiedTimestamps = await verifyBundleTimestamp(bundle.verificationMaterial.timestampVerificationData, signature, this.rawRoot?.timestampAuthorities || []);
|
|
2669
|
+
if (verifiedTimestamps.length < this.options.tsaThreshold) {
|
|
2670
|
+
throw new Error(`Not enough verified TSA timestamps: ${verifiedTimestamps.length} < ${this.options.tsaThreshold}`);
|
|
2671
|
+
}
|
|
2672
|
+
for (const verifiedTimestamp of verifiedTimestamps) {
|
|
2673
|
+
if (!signingCert.validForDate(verifiedTimestamp)) {
|
|
2674
|
+
throw new Error("Certificate was not valid at the time of timestamping");
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
if (bundle.dsseEnvelope) {
|
|
2678
|
+
const payloadBytes = base64ToUint8Array(bundle.dsseEnvelope.payload);
|
|
2679
|
+
const payload = JSON.parse(Uint8ArrayToString(payloadBytes));
|
|
2680
|
+
if (!payload.subject || payload.subject.length === 0) {
|
|
2681
|
+
throw new Error("DSSE payload has no subject");
|
|
2682
|
+
}
|
|
2683
|
+
let artifactDigest;
|
|
2684
|
+
if (isDigestOnly) {
|
|
2685
|
+
artifactDigest = Uint8ArrayToHex(data);
|
|
2686
|
+
} else {
|
|
2687
|
+
artifactDigest = Uint8ArrayToHex(new Uint8Array(await crypto.subtle.digest(HashAlgorithms.SHA256, data)));
|
|
2688
|
+
}
|
|
2689
|
+
let matchedSubject = null;
|
|
2690
|
+
for (const subject of payload.subject) {
|
|
2691
|
+
const subjectDigest = subject.digest?.["sha256"];
|
|
2692
|
+
if (subjectDigest && artifactDigest === subjectDigest.toLowerCase()) {
|
|
2693
|
+
matchedSubject = subject;
|
|
2694
|
+
break;
|
|
2695
|
+
}
|
|
2696
|
+
}
|
|
2697
|
+
if (!matchedSubject) {
|
|
2698
|
+
throw new Error(`Artifact digest ${artifactDigest} does not match any subject in DSSE payload`);
|
|
2699
|
+
}
|
|
2700
|
+
const pae = preAuthEncoding(bundle.dsseEnvelope.payloadType, payloadBytes);
|
|
2701
|
+
const publicKey = await signingCert.publicKeyObj;
|
|
2702
|
+
const verified = await verifySignature(publicKey, pae, signature);
|
|
2703
|
+
if (!verified) {
|
|
2704
|
+
throw new Error("DSSE signature verification failed");
|
|
2705
|
+
}
|
|
2706
|
+
} else {
|
|
2707
|
+
const publicKey = await signingCert.publicKeyObj;
|
|
2708
|
+
if (isDigestOnly) {
|
|
2709
|
+
const verified = await verifySignatureOverDigest(publicKey, data, signature);
|
|
2710
|
+
if (!verified) {
|
|
2711
|
+
throw new Error("Error verifying signature over digest");
|
|
2712
|
+
}
|
|
2713
|
+
} else {
|
|
2714
|
+
const verified = await verifySignature(publicKey, data, signature);
|
|
2715
|
+
if (!verified) {
|
|
2716
|
+
const keyAlg = publicKey.algorithm.name || "unknown";
|
|
2717
|
+
throw new Error(`Error verifying artifact signature. Key algorithm: ${keyAlg}, Data length: ${data.length}, Signature length: ${signature.length}`);
|
|
2718
|
+
}
|
|
2719
|
+
}
|
|
2720
|
+
}
|
|
2721
|
+
return true;
|
|
2722
|
+
}
|
|
2723
|
+
async verifyArtifact(identity, issuer, bundle, data, isDigestOnly = false) {
|
|
2724
|
+
const policy = new AllOf([
|
|
2725
|
+
new Identity({ identity }),
|
|
2726
|
+
new AnyOf([
|
|
2727
|
+
new OIDCIssuerV2(issuer),
|
|
2728
|
+
new OIDCIssuer(issuer)
|
|
2729
|
+
])
|
|
2730
|
+
]);
|
|
2731
|
+
return this.verifyArtifactPolicy(policy, bundle, data, isDigestOnly);
|
|
2732
|
+
}
|
|
2733
|
+
/**
|
|
2734
|
+
* Verify a DSSE bundle using a verification policy.
|
|
2735
|
+
* This matches sigstore-python's verify_dsse API.
|
|
2736
|
+
*
|
|
2737
|
+
* Reference: https://github.com/sigstore/sigstore-python/blob/main/sigstore/verify/verifier.py#L388
|
|
2738
|
+
*
|
|
2739
|
+
* Unlike verify_artifact which verifies an artifact against a bundle,
|
|
2740
|
+
* this method verifies the DSSE envelope itself and returns the payload.
|
|
2741
|
+
* The caller is responsible for checking that the payload matches their
|
|
2742
|
+
* expected artifact (e.g., by checking subjects in an in-toto statement).
|
|
2743
|
+
*
|
|
2744
|
+
* @param bundle - The Sigstore bundle containing the DSSE envelope
|
|
2745
|
+
* @param policy - A verification policy to apply to the signing certificate
|
|
2746
|
+
* @returns The payload type and payload bytes from the verified envelope
|
|
2747
|
+
*/
|
|
2748
|
+
async verifyDsse(bundle, policy) {
|
|
2749
|
+
if (!this.root) {
|
|
2750
|
+
throw new Error("Sigstore root is undefined");
|
|
2751
|
+
}
|
|
2752
|
+
if (!bundle.dsseEnvelope) {
|
|
2753
|
+
throw new Error("Bundle does not contain a DSSE envelope");
|
|
2754
|
+
}
|
|
2755
|
+
const cert = bundle.verificationMaterial.certificate || bundle.verificationMaterial.x509CertificateChain?.certificates[0];
|
|
2756
|
+
if (!cert) {
|
|
2757
|
+
throw new Error("No certificate found in bundle");
|
|
2758
|
+
}
|
|
2759
|
+
const signingCert = X509Certificate.parse(base64ToUint8Array(cert.rawBytes));
|
|
2760
|
+
const certPath = await this.verifyCertificateChain(signingCert.notBefore, signingCert, this.root.certificateAuthorities);
|
|
2761
|
+
const issuerCert = certPath.length > 1 ? certPath[1] : certPath[0];
|
|
2762
|
+
const verifiedSCTs = await this.verifySCT(signingCert, issuerCert, this.root.ctlogs);
|
|
2763
|
+
if (verifiedSCTs.length < this.options.ctlogThreshold) {
|
|
2764
|
+
throw new Error(`Not enough valid SCTs: found ${verifiedSCTs.length}, required ${this.options.ctlogThreshold}`);
|
|
2765
|
+
}
|
|
2766
|
+
policy.verify(signingCert);
|
|
2767
|
+
if (!await this.verifyInclusionPromise(signingCert, bundle, this.root.rekor)) {
|
|
2768
|
+
throw new Error("Inclusion promise validation failed");
|
|
2769
|
+
}
|
|
2770
|
+
await this.verifyInclusionProof(bundle);
|
|
2771
|
+
if (!bundle.dsseEnvelope.signatures || bundle.dsseEnvelope.signatures.length !== 1) {
|
|
2772
|
+
throw new Error(`DSSE envelope must have exactly 1 signature, got ${bundle.dsseEnvelope.signatures?.length ?? 0}`);
|
|
2773
|
+
}
|
|
2774
|
+
const signature = base64ToUint8Array(bundle.dsseEnvelope.signatures[0].sig);
|
|
2775
|
+
const verifiedTimestamps = await verifyBundleTimestamp(bundle.verificationMaterial.timestampVerificationData, signature, this.rawRoot?.timestampAuthorities || []);
|
|
2776
|
+
if (verifiedTimestamps.length < this.options.tsaThreshold) {
|
|
2777
|
+
throw new Error(`Not enough verified TSA timestamps: ${verifiedTimestamps.length} < ${this.options.tsaThreshold}`);
|
|
2778
|
+
}
|
|
2779
|
+
for (const verifiedTimestamp of verifiedTimestamps) {
|
|
2780
|
+
if (!signingCert.validForDate(verifiedTimestamp)) {
|
|
2781
|
+
throw new Error("Certificate was not valid at the time of timestamping");
|
|
2782
|
+
}
|
|
2783
|
+
}
|
|
2784
|
+
for (const entry of bundle.verificationMaterial.tlogEntries) {
|
|
2785
|
+
if (entry.integratedTime) {
|
|
2786
|
+
const integratedDate = new Date(Number(entry.integratedTime) * 1e3);
|
|
2787
|
+
if (!signingCert.validForDate(integratedDate)) {
|
|
2788
|
+
throw new Error("Artifact signing was logged outside of the certificate validity.");
|
|
2789
|
+
}
|
|
2790
|
+
} else {
|
|
2791
|
+
assertRekorV2Timestamp(bundle.verificationMaterial.timestampVerificationData);
|
|
2792
|
+
}
|
|
2793
|
+
}
|
|
2794
|
+
const payloadBytes = base64ToUint8Array(bundle.dsseEnvelope.payload);
|
|
2795
|
+
const pae = preAuthEncoding(bundle.dsseEnvelope.payloadType, payloadBytes);
|
|
2796
|
+
const publicKey = await signingCert.publicKeyObj;
|
|
2797
|
+
const verified = await verifySignature(publicKey, pae, signature);
|
|
2798
|
+
if (!verified) {
|
|
2799
|
+
throw new Error("DSSE signature verification failed");
|
|
2800
|
+
}
|
|
2801
|
+
for (const entry of bundle.verificationMaterial.tlogEntries) {
|
|
2802
|
+
if (entry.kindVersion.kind !== "dsse") {
|
|
2803
|
+
throw new Error(`Expected entry type dsse, got ${entry.kindVersion.kind}`);
|
|
2804
|
+
}
|
|
2805
|
+
await verifyTLogBody(entry, bundle);
|
|
2806
|
+
}
|
|
2807
|
+
return {
|
|
2808
|
+
payloadType: bundle.dsseEnvelope.payloadType,
|
|
2809
|
+
payload: payloadBytes
|
|
2810
|
+
};
|
|
2811
|
+
}
|
|
2812
|
+
};
|
|
2813
|
+
|
|
2814
|
+
export {
|
|
2815
|
+
X509Extension,
|
|
2816
|
+
X509FulcioIssuerV1,
|
|
2817
|
+
X509GitHubWorkflowTriggerExtension,
|
|
2818
|
+
X509GitHubWorkflowSHAExtension,
|
|
2819
|
+
X509GitHubWorkflowNameExtension,
|
|
2820
|
+
X509GitHubWorkflowRepositoryExtension,
|
|
2821
|
+
X509GitHubWorkflowRefExtension,
|
|
2822
|
+
X509FulcioIssuerV2,
|
|
2823
|
+
X509BuildSignerURIExtension,
|
|
2824
|
+
X509BuildSignerDigestExtension,
|
|
2825
|
+
X509RunnerEnvironmentExtension,
|
|
2826
|
+
X509SourceRepositoryURIExtension,
|
|
2827
|
+
X509SourceRepositoryDigestExtension,
|
|
2828
|
+
X509SourceRepositoryRefExtension,
|
|
2829
|
+
X509SourceRepositoryIdentifierExtension,
|
|
2830
|
+
X509SourceRepositoryOwnerURIExtension,
|
|
2831
|
+
X509SourceRepositoryOwnerIdentifierExtension,
|
|
2832
|
+
X509BuildConfigURIExtension,
|
|
2833
|
+
X509BuildConfigDigestExtension,
|
|
2834
|
+
X509BuildTriggerExtension,
|
|
2835
|
+
X509RunInvocationURIExtension,
|
|
2836
|
+
X509SourceRepositoryVisibilityExtension,
|
|
2837
|
+
EXTENSION_OID_SCT,
|
|
2838
|
+
EXTENSION_OID_FULCIO_ISSUER_V1,
|
|
2839
|
+
EXTENSION_OID_GITHUB_WORKFLOW_TRIGGER,
|
|
2840
|
+
EXTENSION_OID_GITHUB_WORKFLOW_SHA,
|
|
2841
|
+
EXTENSION_OID_GITHUB_WORKFLOW_NAME,
|
|
2842
|
+
EXTENSION_OID_GITHUB_WORKFLOW_REPOSITORY,
|
|
2843
|
+
EXTENSION_OID_GITHUB_WORKFLOW_REF,
|
|
2844
|
+
EXTENSION_OID_OTHERNAME,
|
|
2845
|
+
EXTENSION_OID_FULCIO_ISSUER_V2,
|
|
2846
|
+
EXTENSION_OID_BUILD_SIGNER_URI,
|
|
2847
|
+
EXTENSION_OID_BUILD_SIGNER_DIGEST,
|
|
2848
|
+
EXTENSION_OID_RUNNER_ENVIRONMENT,
|
|
2849
|
+
EXTENSION_OID_SOURCE_REPOSITORY_URI,
|
|
2850
|
+
EXTENSION_OID_SOURCE_REPOSITORY_DIGEST,
|
|
2851
|
+
EXTENSION_OID_SOURCE_REPOSITORY_REF,
|
|
2852
|
+
EXTENSION_OID_SOURCE_REPOSITORY_IDENTIFIER,
|
|
2853
|
+
EXTENSION_OID_SOURCE_REPOSITORY_OWNER_URI,
|
|
2854
|
+
EXTENSION_OID_SOURCE_REPOSITORY_OWNER_IDENTIFIER,
|
|
2855
|
+
EXTENSION_OID_BUILD_CONFIG_URI,
|
|
2856
|
+
EXTENSION_OID_BUILD_CONFIG_DIGEST,
|
|
2857
|
+
EXTENSION_OID_BUILD_TRIGGER,
|
|
2858
|
+
EXTENSION_OID_RUN_INVOCATION_URI,
|
|
2859
|
+
EXTENSION_OID_SOURCE_REPOSITORY_VISIBILITY,
|
|
2860
|
+
X509Certificate,
|
|
2861
|
+
CertificateChainVerifier,
|
|
2862
|
+
verifyRFC3161Timestamp,
|
|
2863
|
+
verifyBundleTimestamp,
|
|
2864
|
+
TrustedRootProvider,
|
|
2865
|
+
VerificationError,
|
|
2866
|
+
TimestampError,
|
|
2867
|
+
CertificateError,
|
|
2868
|
+
TLogError,
|
|
2869
|
+
SignatureError,
|
|
2870
|
+
PolicyError,
|
|
2871
|
+
GITHUB_OIDC_ISSUER,
|
|
2872
|
+
OIDCIssuer,
|
|
2873
|
+
GitHubWorkflowTrigger,
|
|
2874
|
+
GitHubWorkflowSHA,
|
|
2875
|
+
GitHubWorkflowName,
|
|
2876
|
+
GitHubWorkflowRepository,
|
|
2877
|
+
GitHubWorkflowRef,
|
|
2878
|
+
OIDCIssuerV2,
|
|
2879
|
+
OIDCBuildSignerURI,
|
|
2880
|
+
OIDCBuildSignerDigest,
|
|
2881
|
+
OIDCRunnerEnvironment,
|
|
2882
|
+
OIDCSourceRepositoryURI,
|
|
2883
|
+
OIDCSourceRepositoryDigest,
|
|
2884
|
+
OIDCSourceRepositoryRef,
|
|
2885
|
+
OIDCSourceRepositoryIdentifier,
|
|
2886
|
+
OIDCSourceRepositoryOwnerURI,
|
|
2887
|
+
OIDCSourceRepositoryOwnerIdentifier,
|
|
2888
|
+
OIDCBuildConfigURI,
|
|
2889
|
+
OIDCBuildConfigDigest,
|
|
2890
|
+
OIDCBuildTrigger,
|
|
2891
|
+
OIDCRunInvocationURI,
|
|
2892
|
+
OIDCSourceRepositoryVisibility,
|
|
2893
|
+
AnyOf,
|
|
2894
|
+
AllOf,
|
|
2895
|
+
Identity,
|
|
2896
|
+
SigstoreVerifier
|
|
2897
|
+
};
|