@freedomofpress/sigstore-browser 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/.github/workflows/conformance.yml +29 -0
  2. package/.github/workflows/publish.yml +45 -0
  3. package/README.md +10 -0
  4. package/dist/asn1/error.d.ts +5 -0
  5. package/dist/asn1/error.d.ts.map +1 -0
  6. package/dist/asn1/error.js +20 -0
  7. package/dist/asn1/error.js.map +1 -0
  8. package/dist/asn1/index.d.ts +2 -0
  9. package/dist/asn1/index.d.ts.map +1 -0
  10. package/dist/asn1/index.js +17 -0
  11. package/dist/asn1/index.js.map +1 -0
  12. package/dist/asn1/length.d.ts +4 -0
  13. package/dist/asn1/length.d.ts.map +1 -0
  14. package/dist/asn1/length.js +59 -0
  15. package/dist/asn1/length.js.map +1 -0
  16. package/dist/asn1/obj.d.ts +15 -0
  17. package/dist/asn1/obj.d.ts.map +1 -0
  18. package/dist/asn1/obj.js +153 -0
  19. package/dist/asn1/obj.js.map +1 -0
  20. package/dist/asn1/parse.d.ts +7 -0
  21. package/dist/asn1/parse.d.ts.map +1 -0
  22. package/dist/asn1/parse.js +118 -0
  23. package/dist/asn1/parse.js.map +1 -0
  24. package/dist/asn1/tag.d.ts +17 -0
  25. package/dist/asn1/tag.d.ts.map +1 -0
  26. package/dist/asn1/tag.js +86 -0
  27. package/dist/asn1/tag.js.map +1 -0
  28. package/dist/bundle.d.ts +87 -0
  29. package/dist/bundle.d.ts.map +1 -0
  30. package/dist/bundle.js +2 -0
  31. package/dist/bundle.js.map +1 -0
  32. package/dist/canonicalize.d.ts +2 -0
  33. package/dist/canonicalize.d.ts.map +1 -0
  34. package/dist/canonicalize.js +64 -0
  35. package/dist/canonicalize.js.map +1 -0
  36. package/dist/cli.d.ts +3 -0
  37. package/dist/cli.d.ts.map +1 -0
  38. package/dist/cli.js +217 -0
  39. package/dist/cli.js.map +1 -0
  40. package/dist/crypto.d.ts +5 -0
  41. package/dist/crypto.d.ts.map +1 -0
  42. package/dist/crypto.js +260 -0
  43. package/dist/crypto.js.map +1 -0
  44. package/dist/dsse.d.ts +2 -0
  45. package/dist/dsse.d.ts.map +1 -0
  46. package/dist/dsse.js +42 -0
  47. package/dist/dsse.js.map +1 -0
  48. package/dist/encoding.d.ts +17 -0
  49. package/dist/encoding.d.ts.map +1 -0
  50. package/dist/encoding.js +112 -0
  51. package/dist/encoding.js.map +1 -0
  52. package/dist/errors.d.ts +39 -0
  53. package/dist/errors.d.ts.map +1 -0
  54. package/dist/errors.js +79 -0
  55. package/dist/errors.js.map +1 -0
  56. package/dist/index.d.ts +8 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +5 -0
  59. package/dist/index.js.map +1 -0
  60. package/dist/interfaces.d.ts +104 -0
  61. package/dist/interfaces.d.ts.map +1 -0
  62. package/dist/interfaces.js +26 -0
  63. package/dist/interfaces.js.map +1 -0
  64. package/dist/oid.d.ts +5 -0
  65. package/dist/oid.d.ts.map +1 -0
  66. package/dist/oid.js +25 -0
  67. package/dist/oid.js.map +1 -0
  68. package/dist/pem.d.ts +3 -0
  69. package/dist/pem.d.ts.map +1 -0
  70. package/dist/pem.js +41 -0
  71. package/dist/pem.js.map +1 -0
  72. package/dist/rfc3161/error.d.ts +3 -0
  73. package/dist/rfc3161/error.d.ts.map +1 -0
  74. package/dist/rfc3161/error.js +18 -0
  75. package/dist/rfc3161/error.js.map +1 -0
  76. package/dist/rfc3161/index.d.ts +2 -0
  77. package/dist/rfc3161/index.d.ts.map +1 -0
  78. package/dist/rfc3161/index.js +17 -0
  79. package/dist/rfc3161/index.js.map +1 -0
  80. package/dist/rfc3161/timestamp.d.ts +36 -0
  81. package/dist/rfc3161/timestamp.d.ts.map +1 -0
  82. package/dist/rfc3161/timestamp.js +203 -0
  83. package/dist/rfc3161/timestamp.js.map +1 -0
  84. package/dist/rfc3161/tstinfo.d.ts +13 -0
  85. package/dist/rfc3161/tstinfo.d.ts.map +1 -0
  86. package/dist/rfc3161/tstinfo.js +47 -0
  87. package/dist/rfc3161/tstinfo.js.map +1 -0
  88. package/dist/sigstore.d.ts +33 -0
  89. package/dist/sigstore.d.ts.map +1 -0
  90. package/dist/sigstore.js +531 -0
  91. package/dist/sigstore.js.map +1 -0
  92. package/dist/stream.d.ts +22 -0
  93. package/dist/stream.d.ts.map +1 -0
  94. package/dist/stream.js +114 -0
  95. package/dist/stream.js.map +1 -0
  96. package/dist/timestamp/tsa.d.ts +24 -0
  97. package/dist/timestamp/tsa.d.ts.map +1 -0
  98. package/dist/timestamp/tsa.js +150 -0
  99. package/dist/timestamp/tsa.js.map +1 -0
  100. package/dist/tlog/body.d.ts +8 -0
  101. package/dist/tlog/body.d.ts.map +1 -0
  102. package/dist/tlog/body.js +45 -0
  103. package/dist/tlog/body.js.map +1 -0
  104. package/dist/tlog/checkpoint.d.ts +23 -0
  105. package/dist/tlog/checkpoint.d.ts.map +1 -0
  106. package/dist/tlog/checkpoint.js +187 -0
  107. package/dist/tlog/checkpoint.js.map +1 -0
  108. package/dist/tlog/dsse.d.ts +4 -0
  109. package/dist/tlog/dsse.d.ts.map +1 -0
  110. package/dist/tlog/dsse.js +85 -0
  111. package/dist/tlog/dsse.js.map +1 -0
  112. package/dist/tlog/hashedrekord.d.ts +4 -0
  113. package/dist/tlog/hashedrekord.d.ts.map +1 -0
  114. package/dist/tlog/hashedrekord.js +63 -0
  115. package/dist/tlog/hashedrekord.js.map +1 -0
  116. package/dist/tlog/intoto.d.ts +4 -0
  117. package/dist/tlog/intoto.d.ts.map +1 -0
  118. package/dist/tlog/intoto.js +50 -0
  119. package/dist/tlog/intoto.js.map +1 -0
  120. package/dist/tlog/merkle.d.ts +3 -0
  121. package/dist/tlog/merkle.d.ts.map +1 -0
  122. package/dist/tlog/merkle.js +112 -0
  123. package/dist/tlog/merkle.js.map +1 -0
  124. package/dist/trust/tuf-root.json +1 -0
  125. package/dist/trust/tuf.d.ts +95 -0
  126. package/dist/trust/tuf.d.ts.map +1 -0
  127. package/dist/trust/tuf.js +150 -0
  128. package/dist/trust/tuf.js.map +1 -0
  129. package/dist/x509/cert.d.ts +52 -0
  130. package/dist/x509/cert.d.ts.map +1 -0
  131. package/dist/x509/cert.js +256 -0
  132. package/dist/x509/cert.js.map +1 -0
  133. package/dist/x509/chain.d.ts +20 -0
  134. package/dist/x509/chain.d.ts.map +1 -0
  135. package/dist/x509/chain.js +141 -0
  136. package/dist/x509/chain.js.map +1 -0
  137. package/dist/x509/ext.d.ts +48 -0
  138. package/dist/x509/ext.d.ts.map +1 -0
  139. package/dist/x509/ext.js +164 -0
  140. package/dist/x509/ext.js.map +1 -0
  141. package/dist/x509/index.d.ts +4 -0
  142. package/dist/x509/index.d.ts.map +1 -0
  143. package/dist/x509/index.js +19 -0
  144. package/dist/x509/index.js.map +1 -0
  145. package/dist/x509/sct.d.ts +25 -0
  146. package/dist/x509/sct.d.ts.map +1 -0
  147. package/dist/x509/sct.js +123 -0
  148. package/dist/x509/sct.js.map +1 -0
  149. package/eslint.config.mjs +31 -0
  150. package/package.json +39 -0
  151. package/src/asn1/error.ts +18 -0
  152. package/src/asn1/index.ts +16 -0
  153. package/src/asn1/length.ts +71 -0
  154. package/src/asn1/obj.ts +184 -0
  155. package/src/asn1/parse.ts +146 -0
  156. package/src/asn1/tag.ts +105 -0
  157. package/src/bundle.ts +99 -0
  158. package/src/canonicalize.ts +61 -0
  159. package/src/cli.ts +285 -0
  160. package/src/crypto.ts +310 -0
  161. package/src/dsse.ts +49 -0
  162. package/src/encoding.ts +141 -0
  163. package/src/errors.ts +82 -0
  164. package/src/index.browser.test.ts +219 -0
  165. package/src/index.ts +14 -0
  166. package/src/interfaces.ts +118 -0
  167. package/src/oid.ts +28 -0
  168. package/src/pem.ts +48 -0
  169. package/src/rfc3161/error.ts +16 -0
  170. package/src/rfc3161/index.ts +17 -0
  171. package/src/rfc3161/timestamp.ts +270 -0
  172. package/src/rfc3161/tstinfo.ts +80 -0
  173. package/src/sigstore.ts +728 -0
  174. package/src/stream.ts +141 -0
  175. package/src/timestamp/tsa.ts +205 -0
  176. package/src/tlog/body.ts +65 -0
  177. package/src/tlog/checkpoint.ts +248 -0
  178. package/src/tlog/dsse.ts +147 -0
  179. package/src/tlog/hashedrekord.ts +130 -0
  180. package/src/tlog/intoto.ts +102 -0
  181. package/src/tlog/merkle.ts +152 -0
  182. package/src/trust/README.md +38 -0
  183. package/src/trust/tuf-root.json +1 -0
  184. package/src/trust/tuf.ts +223 -0
  185. package/src/types/tuf-browser.d.ts +13 -0
  186. package/src/x509/cert.ts +319 -0
  187. package/src/x509/chain.ts +212 -0
  188. package/src/x509/ext.ts +212 -0
  189. package/src/x509/index.ts +19 -0
  190. package/src/x509/sct.ts +154 -0
  191. package/tsconfig.json +18 -0
  192. package/vite.config.playwright.ts +26 -0
  193. package/vite.config.ts +18 -0
@@ -0,0 +1,164 @@
1
+ import { toArrayBuffer, Uint8ArrayToString } from "../encoding.js";
2
+ import { ByteStream } from "../stream.js";
3
+ import { SignedCertificateTimestamp } from "./sct.js";
4
+ // https://www.rfc-editor.org/rfc/rfc5280#section-4.1
5
+ export class X509Extension {
6
+ root;
7
+ constructor(asn1) {
8
+ this.root = asn1;
9
+ }
10
+ get oid() {
11
+ return this.root.subs[0].toOID();
12
+ }
13
+ get critical() {
14
+ // The critical field is optional and will be the second element of the
15
+ // extension sequence if present. Default to false if not present.
16
+ return this.root.subs.length === 3 ? this.root.subs[1].toBoolean() : false;
17
+ }
18
+ get value() {
19
+ return this.extnValueObj.value;
20
+ }
21
+ get valueObj() {
22
+ return this.extnValueObj;
23
+ }
24
+ get extnValueObj() {
25
+ // The extnValue field will be the last element of the extension sequence
26
+ return this.root.subs[this.root.subs.length - 1];
27
+ }
28
+ }
29
+ // https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.9
30
+ export class X509BasicConstraintsExtension extends X509Extension {
31
+ get isCA() {
32
+ return this.sequence.subs[0]?.toBoolean() ?? false;
33
+ }
34
+ get pathLenConstraint() {
35
+ return this.sequence.subs.length > 1
36
+ ? this.sequence.subs[1].toInteger()
37
+ : undefined;
38
+ }
39
+ // The extnValue field contains a single sequence wrapping the isCA and
40
+ // pathLenConstraint.
41
+ get sequence() {
42
+ return this.extnValueObj.subs[0];
43
+ }
44
+ }
45
+ // https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.3
46
+ export class X509KeyUsageExtension extends X509Extension {
47
+ get digitalSignature() {
48
+ return this.bitString[0] === 1;
49
+ }
50
+ get keyCertSign() {
51
+ return this.bitString[5] === 1;
52
+ }
53
+ get crlSign() {
54
+ return this.bitString[6] === 1;
55
+ }
56
+ // The extnValue field contains a single bit string which is a bit mask
57
+ // indicating which key usages are enabled.
58
+ get bitString() {
59
+ return this.extnValueObj.subs[0].toBitString();
60
+ }
61
+ }
62
+ // https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.6
63
+ export class X509SubjectAlternativeNameExtension extends X509Extension {
64
+ get rfc822Name() {
65
+ const rfc822Name = this.findGeneralName(0x01)?.value;
66
+ if (rfc822Name === undefined) {
67
+ return undefined;
68
+ }
69
+ else {
70
+ return Uint8ArrayToString(rfc822Name);
71
+ }
72
+ }
73
+ get uri() {
74
+ const uri = this.findGeneralName(0x06)?.value;
75
+ if (uri === undefined) {
76
+ return undefined;
77
+ }
78
+ else {
79
+ return Uint8ArrayToString(uri);
80
+ }
81
+ }
82
+ // Retrieve the value of an otherName with the given OID.
83
+ otherName(oid) {
84
+ const otherName = this.findGeneralName(0x00);
85
+ if (otherName === undefined) {
86
+ return undefined;
87
+ }
88
+ // The otherName is a sequence containing an OID and a value.
89
+ // Need to check that the OID matches the one we're looking for.
90
+ const otherNameOID = otherName.subs[0].toOID();
91
+ if (otherNameOID !== oid) {
92
+ return undefined;
93
+ }
94
+ // The otherNameValue is a sequence containing the actual value.
95
+ const otherNameValue = otherName.subs[1];
96
+ return Uint8ArrayToString(otherNameValue.subs[0].value);
97
+ }
98
+ findGeneralName(tag) {
99
+ return this.generalNames.find((gn) => gn.tag.isContextSpecific(tag));
100
+ }
101
+ // The extnValue field contains a sequence of GeneralNames.
102
+ get generalNames() {
103
+ return this.extnValueObj.subs[0].subs;
104
+ }
105
+ }
106
+ // https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.1
107
+ export class X509AuthorityKeyIDExtension extends X509Extension {
108
+ get keyIdentifier() {
109
+ return this.findSequenceMember(0x00)?.value;
110
+ }
111
+ findSequenceMember(tag) {
112
+ return this.sequence.subs.find((el) => el.tag.isContextSpecific(tag));
113
+ }
114
+ // The extnValue field contains a single sequence wrapping the keyIdentifier
115
+ get sequence() {
116
+ return this.extnValueObj.subs[0];
117
+ }
118
+ }
119
+ // https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.2
120
+ export class X509SubjectKeyIDExtension extends X509Extension {
121
+ get keyIdentifier() {
122
+ return this.extnValueObj.subs[0].value;
123
+ }
124
+ }
125
+ // Fulcio Issuer V1 extension - OID 1.3.6.1.4.1.57264.1.1
126
+ // Simple OCTET STRING containing the issuer
127
+ export class X509FulcioIssuerV1 extends X509Extension {
128
+ get issuer() {
129
+ return Uint8ArrayToString(this.extnValueObj.value);
130
+ }
131
+ }
132
+ // Fulcio Issuer V2 extension - OID 1.3.6.1.4.1.57264.1.8
133
+ // SEQUENCE containing the issuer as the first element
134
+ export class X509FulcioIssuerV2 extends X509Extension {
135
+ get issuer() {
136
+ return Uint8ArrayToString(this.extnValueObj.subs[0].value);
137
+ }
138
+ }
139
+ // https://www.rfc-editor.org/rfc/rfc6962#section-3.3
140
+ export class X509SCTExtension extends X509Extension {
141
+ constructor(asn1) {
142
+ super(asn1);
143
+ }
144
+ get signedCertificateTimestamps() {
145
+ const buf = this.extnValueObj.subs[0].value;
146
+ const stream = new ByteStream(toArrayBuffer(buf));
147
+ // The overall list length is encoded in the first two bytes -- note this
148
+ // is the length of the list in bytes, NOT the number of SCTs in the list
149
+ const end = stream.getUint16() + 2;
150
+ const sctList = [];
151
+ while (stream.position < end) {
152
+ // Read the length of the next SCT
153
+ const sctLength = stream.getUint16();
154
+ // Slice out the bytes for the next SCT and parse it
155
+ const sct = stream.getBlock(sctLength);
156
+ sctList.push(SignedCertificateTimestamp.parse(sct));
157
+ }
158
+ if (stream.position !== end) {
159
+ throw new Error("SCT list length does not match actual length");
160
+ }
161
+ return sctList;
162
+ }
163
+ }
164
+ //# sourceMappingURL=ext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ext.js","sourceRoot":"","sources":["../../src/x509/ext.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { EXTENSION_OID_SCT, X509Certificate } from "./cert.js";
2
+ export { X509SCTExtension } from "./ext.js";
3
+ export { CertificateChainVerifier } from "./chain.js";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/x509/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,19 @@
1
+ /*
2
+ Copyright 2023 The Sigstore Authors.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+ export { EXTENSION_OID_SCT, X509Certificate } from "./cert.js";
17
+ export { X509SCTExtension } from "./ext.js";
18
+ export { CertificateChainVerifier } from "./chain.js";
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/x509/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;EAcE;AAEF,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,25 @@
1
+ interface SCTOptions {
2
+ version: number;
3
+ logID: Uint8Array;
4
+ timestamp: Uint8Array;
5
+ extensions: Uint8Array;
6
+ hashAlgorithm: number;
7
+ signatureAlgorithm: number;
8
+ signature: Uint8Array;
9
+ }
10
+ export declare class SignedCertificateTimestamp {
11
+ readonly version: number;
12
+ readonly logID: Uint8Array;
13
+ readonly timestamp: Uint8Array;
14
+ readonly extensions: Uint8Array;
15
+ readonly hashAlgorithm: number;
16
+ readonly signatureAlgorithm: number;
17
+ readonly signature: Uint8Array;
18
+ constructor(options: SCTOptions);
19
+ get datetime(): Date;
20
+ get algorithm(): string;
21
+ verify(preCert: Uint8Array, key: CryptoKey): Promise<boolean>;
22
+ static parse(buf: Uint8Array): SignedCertificateTimestamp;
23
+ }
24
+ export {};
25
+ //# sourceMappingURL=sct.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sct.d.ts","sourceRoot":"","sources":["../../src/x509/sct.ts"],"names":[],"mappings":"AAmBA,UAAU,UAAU;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,UAAU,CAAC;IACtB,UAAU,EAAE,UAAU,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,UAAU,CAAC;CACvB;AAED,qBAAa,0BAA0B;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;gBAEnB,OAAO,EAAE,UAAU;IAU/B,IAAI,QAAQ,IAAI,IAAI,CAEnB;IAID,IAAI,SAAS,IAAI,MAAM,CA0BtB;IAEY,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;WA8B5D,KAAK,CAAC,GAAG,EAAE,UAAU,GAAG,0BAA0B;CAyCjE"}
@@ -0,0 +1,123 @@
1
+ /*
2
+ Copyright 2023 The Sigstore Authors.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+ import { verifySignature } from "../crypto.js";
17
+ import { readBigInt64BE, toArrayBuffer } from "../encoding.js";
18
+ import { ByteStream } from "../stream.js";
19
+ export class SignedCertificateTimestamp {
20
+ version;
21
+ logID;
22
+ timestamp;
23
+ extensions;
24
+ hashAlgorithm;
25
+ signatureAlgorithm;
26
+ signature;
27
+ constructor(options) {
28
+ this.version = options.version;
29
+ this.logID = options.logID;
30
+ this.timestamp = options.timestamp;
31
+ this.extensions = options.extensions;
32
+ this.hashAlgorithm = options.hashAlgorithm;
33
+ this.signatureAlgorithm = options.signatureAlgorithm;
34
+ this.signature = options.signature;
35
+ }
36
+ get datetime() {
37
+ return new Date(Number(readBigInt64BE(this.timestamp)));
38
+ }
39
+ // Returns the hash algorithm used to generate the SCT's signature.
40
+ // https://www.rfc-editor.org/rfc/rfc5246#section-7.4.1.4.1
41
+ get algorithm() {
42
+ switch (this.hashAlgorithm) {
43
+ /* istanbul ignore next */
44
+ case 0:
45
+ return "none";
46
+ /* istanbul ignore next */
47
+ case 1:
48
+ return "md5";
49
+ /* istanbul ignore next */
50
+ case 2:
51
+ return "sha1";
52
+ /* istanbul ignore next */
53
+ case 3:
54
+ return "sha224";
55
+ case 4:
56
+ return "sha256";
57
+ /* istanbul ignore next */
58
+ case 5:
59
+ return "sha384";
60
+ /* istanbul ignore next */
61
+ case 6:
62
+ return "sha512";
63
+ /* istanbul ignore next */
64
+ default:
65
+ return "unknown";
66
+ }
67
+ }
68
+ async verify(preCert, key) {
69
+ // Assemble the digitally-signed struct (the data over which the signature
70
+ // was generated).
71
+ // https://www.rfc-editor.org/rfc/rfc6962#section-3.2
72
+ const stream = new ByteStream();
73
+ stream.appendChar(this.version);
74
+ stream.appendChar(0x00); // SignatureType = certificate_timestamp(0)
75
+ stream.appendView(this.timestamp);
76
+ stream.appendUint16(0x01); // LogEntryType = precert_entry(1)
77
+ stream.appendView(preCert);
78
+ stream.appendUint16(this.extensions.byteLength);
79
+ /* istanbul ignore next - extensions are very uncommon */
80
+ if (this.extensions.byteLength > 0) {
81
+ stream.appendView(this.extensions);
82
+ }
83
+ return await verifySignature(key, stream.buffer, this.signature, this.algorithm);
84
+ }
85
+ // Parses a SignedCertificateTimestamp from a buffer. SCTs are encoded using
86
+ // TLS encoding which means the fields and lengths of most fields are
87
+ // specified as part of the SCT and TLS specs.
88
+ // https://www.rfc-editor.org/rfc/rfc6962#section-3.2
89
+ // https://www.rfc-editor.org/rfc/rfc5246#section-7.4.1.4.1
90
+ static parse(buf) {
91
+ const stream = new ByteStream(toArrayBuffer(buf));
92
+ // Version - enum { v1(0), (255) }
93
+ const version = stream.getUint8();
94
+ // Log ID - struct { opaque key_id[32]; }
95
+ const logID = stream.getBlock(32);
96
+ // Timestamp - uint64
97
+ const timestamp = stream.getBlock(8);
98
+ // Extensions - opaque extensions<0..2^16-1>;
99
+ const extenstionLength = stream.getUint16();
100
+ const extensions = stream.getBlock(extenstionLength);
101
+ // Hash algo - enum { sha256(4), . . . (255) }
102
+ const hashAlgorithm = stream.getUint8();
103
+ // Signature algo - enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
104
+ const signatureAlgorithm = stream.getUint8();
105
+ // Signature - opaque signature<0..2^16-1>;
106
+ const sigLength = stream.getUint16();
107
+ const signature = stream.getBlock(sigLength);
108
+ // Check that we read the entire buffer
109
+ if (stream.position !== buf.length) {
110
+ throw new Error("SCT buffer length mismatch");
111
+ }
112
+ return new SignedCertificateTimestamp({
113
+ version,
114
+ logID,
115
+ timestamp,
116
+ extensions,
117
+ hashAlgorithm,
118
+ signatureAlgorithm,
119
+ signature,
120
+ });
121
+ }
122
+ }
123
+ //# sourceMappingURL=sct.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sct.js","sourceRoot":"","sources":["../../src/x509/sct.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import simpleImportSort from "eslint-plugin-simple-import-sort";
2
+ import * as tseslint from "typescript-eslint";
3
+
4
+ export default [
5
+ ...tseslint.configs.recommended,
6
+
7
+ {
8
+ files: ["**/*.{js,ts}"],
9
+ languageOptions: {
10
+ ecmaVersion: 2022,
11
+ sourceType: "module",
12
+ },
13
+ plugins: {
14
+ "simple-import-sort": simpleImportSort,
15
+ },
16
+ rules: {
17
+ "simple-import-sort/imports": "error",
18
+ "simple-import-sort/exports": "error",
19
+ "@typescript-eslint/no-non-null-assertion": "warn",
20
+ "@typescript-eslint/no-unused-vars": [
21
+ "error",
22
+ {
23
+ argsIgnorePattern: "^_",
24
+ varsIgnorePattern: "^_",
25
+ },
26
+ ],
27
+
28
+ "no-delete-var": "off",
29
+ },
30
+ },
31
+ ];
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@freedomofpress/sigstore-browser",
3
+ "version": "0.1.0",
4
+ "description": "A minimal browser-only Sigstore verification library.",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ }
12
+ },
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "test": "vitest run",
16
+ "coverage": "vitest run --coverage",
17
+ "lint": "npx eslint . --fix && npx prettier --write ."
18
+ },
19
+ "keywords": [
20
+ "sigstore",
21
+ "rekor",
22
+ "browser",
23
+ "typescript"
24
+ ],
25
+ "author": "Giulio B",
26
+ "license": "MIT",
27
+ "devDependencies": {
28
+ "@types/node": "^24.0.14",
29
+ "@vitest/coverage-v8": "^3.2.4",
30
+ "eslint-plugin-simple-import-sort": "^12.1.1",
31
+ "typescript": "^5.8.3",
32
+ "typescript-eslint": "^8.37.0",
33
+ "vitest": "^3.2.4"
34
+ },
35
+ "dependencies": {
36
+ "@noble/curves": "^2.0.1",
37
+ "tuf-browser": "^0.1.1"
38
+ }
39
+ }
@@ -0,0 +1,18 @@
1
+ /*
2
+ Copyright 2023 The Sigstore Authors.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+ export class ASN1ParseError extends Error {}
17
+
18
+ export class ASN1TypeError extends Error {}
@@ -0,0 +1,16 @@
1
+ /*
2
+ Copyright 2023 The Sigstore Authors.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+ export { ASN1Obj } from "./obj.js";
@@ -0,0 +1,71 @@
1
+ /*
2
+ Copyright 2023 The Sigstore Authors.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+
17
+ import { ByteStream } from "../stream.js";
18
+ import { ASN1ParseError } from "./error.js";
19
+
20
+ // Decodes the length of a DER-encoded ANS.1 element from the supplied stream.
21
+ // https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-encoded-length-and-value-bytes
22
+ export function decodeLength(stream: ByteStream): number {
23
+ const buf = stream.getUint8();
24
+
25
+ // If the most significant bit is UNSET the length is just the value of the
26
+ // byte.
27
+ if ((buf & 0x80) === 0x00) {
28
+ return buf;
29
+ }
30
+
31
+ // Otherwise, the lower 7 bits of the first byte indicate the number of bytes
32
+ // that follow to encode the length.
33
+ const byteCount = buf & 0x7f;
34
+
35
+ // Ensure the encoded length can safely fit in a JS number.
36
+ if (byteCount > 6) {
37
+ throw new ASN1ParseError("length exceeds 6 byte limit");
38
+ }
39
+
40
+ // Iterate over the bytes that encode the length.
41
+ let len = 0;
42
+ for (let i = 0; i < byteCount; i++) {
43
+ len = len * 256 + stream.getUint8();
44
+ }
45
+
46
+ // This is a valid ASN.1 length encoding, but we don't support it.
47
+ if (len === 0) {
48
+ throw new ASN1ParseError("indefinite length encoding not supported");
49
+ }
50
+
51
+ return len;
52
+ }
53
+
54
+ // Translates the supplied value to a DER-encoded length.
55
+ export function encodeLength(len: number): Uint8Array {
56
+ if (len < 128) {
57
+ return new Uint8Array([len]);
58
+ }
59
+
60
+ // Bitwise operations on large numbers are not supported in JS, so we need to
61
+ // use BigInts.
62
+ let val = BigInt(len);
63
+ const bytes = [];
64
+
65
+ while (val > 0n) {
66
+ bytes.unshift(Number(val & 255n));
67
+ val = val >> 8n;
68
+ }
69
+
70
+ return new Uint8Array([0x80 | bytes.length, ...bytes]);
71
+ }