From e86a385ff704f8c5c3f2d34f4cfcc221439b130d Mon Sep 17 00:00:00 2001 From: Brian DeHamer Date: Tue, 16 Jan 2024 11:23:59 -0800 Subject: [PATCH] deps: sigstore@2.2.0 Signed-off-by: Brian DeHamer --- DEPENDENCIES.md | 6 + node_modules/.gitignore | 2 + .../@sigstore/bundle/dist/serialized.js | 7 + node_modules/@sigstore/bundle/package.json | 2 +- node_modules/@sigstore/core/LICENSE | 202 ++++++++++++++++++ .../util => @sigstore/core/dist}/asn1/dump.js | 0 .../core/dist}/asn1/error.js | 0 .../core/dist}/asn1/index.js | 0 .../core/dist}/asn1/length.js | 0 .../util => @sigstore/core/dist}/asn1/obj.js | 0 .../core/dist}/asn1/parse.js | 4 +- .../util => @sigstore/core/dist}/asn1/tag.js | 0 .../util => @sigstore/core/dist}/crypto.js | 34 +-- .../{sign/dist/util => core/dist}/dsse.js | 10 +- .../{sign/dist/util => core/dist}/encoding.js | 0 .../util => @sigstore/core/dist}/index.js | 15 +- .../dist/util => @sigstore/core/dist}/json.js | 4 +- node_modules/@sigstore/core/dist/oid.js | 14 ++ .../dist/util => @sigstore/core/dist}/pem.js | 2 +- .../core/dist/rfc3161/error.js} | 8 +- .../pem.js => core/dist/rfc3161/index.js} | 15 +- .../@sigstore/core/dist/rfc3161/timestamp.js | 201 +++++++++++++++++ .../@sigstore/core/dist/rfc3161/tstinfo.js | 61 ++++++ .../util => @sigstore/core/dist}/stream.js | 0 .../core}/dist/x509/cert.js | 166 +++++++------- .../core}/dist/x509/ext.js | 34 +-- .../crypto.js => core/dist/x509/index.js} | 18 +- .../core}/dist/x509/sct.js | 60 +++++- node_modules/@sigstore/core/package.json | 31 +++ .../@sigstore/sign/dist/util/index.js | 13 +- node_modules/@sigstore/sign/dist/util/json.js | 61 ------ node_modules/@sigstore/sign/dist/util/oidc.js | 27 +-- node_modules/@sigstore/sign/package.json | 9 +- .../@sigstore/verify/dist/bundle/dsse.js | 43 ++++ .../@sigstore/verify/dist/bundle/index.js | 53 +++++ .../@sigstore/verify/dist/bundle/message.js | 36 ++++ .../verify}/dist/error.js | 9 +- node_modules/@sigstore/verify/dist/index.js | 27 +++ .../verify/dist/key/certificate.js} | 90 +++++--- .../@sigstore/verify/dist/key/index.js | 72 +++++++ node_modules/@sigstore/verify/dist/key/sct.js | 79 +++++++ node_modules/@sigstore/verify/dist/policy.js | 25 +++ .../verify/dist/shared.types.js} | 0 .../verify/dist/timestamp}/checkpoint.js | 122 ++++++----- .../@sigstore/verify/dist/timestamp/index.js | 47 ++++ .../verify/dist/timestamp}/merkle.js | 48 ++--- .../@sigstore/verify/dist/timestamp/set.js | 61 ++++++ .../@sigstore/verify/dist/timestamp/tsa.js | 74 +++++++ .../@sigstore/verify/dist/tlog/dsse.js | 58 +++++ .../verify/dist/tlog/hashedrekord.js | 52 +++++ .../@sigstore/verify/dist/tlog/index.js | 48 +++++ .../@sigstore/verify/dist/tlog/intoto.js | 62 ++++++ .../@sigstore/verify/dist/trust/filter.js | 24 +++ .../@sigstore/verify/dist/trust/index.js | 75 +++++++ .../verify/dist/trust/trust.types.js | 2 + .../@sigstore/verify/dist/verifier.js | 141 ++++++++++++ node_modules/@sigstore/verify/package.json | 36 ++++ node_modules/sigstore/dist/ca/verify/chain.js | 63 ------ node_modules/sigstore/dist/ca/verify/index.js | 22 -- node_modules/sigstore/dist/ca/verify/sct.js | 30 --- .../sigstore/dist/ca/verify/signer.js | 146 ------------- node_modules/sigstore/dist/config.js | 117 +++------- node_modules/sigstore/dist/index.js | 6 +- node_modules/sigstore/dist/sigstore.js | 19 +- .../sigstore/dist/tlog/verify/body.js | 152 ------------- .../sigstore/dist/tlog/verify/index.js | 92 -------- node_modules/sigstore/dist/tlog/verify/set.js | 64 ------ node_modules/sigstore/dist/types/sigstore.js | 27 --- node_modules/sigstore/dist/util/dsse.js | 25 --- node_modules/sigstore/dist/util/encoding.js | 46 ---- node_modules/sigstore/dist/verify.js | 160 -------------- node_modules/sigstore/package.json | 14 +- package-lock.json | 54 +++-- workspaces/libnpmpublish/package.json | 2 +- 74 files changed, 2008 insertions(+), 1321 deletions(-) create mode 100644 node_modules/@sigstore/core/LICENSE rename node_modules/{sigstore/dist/util => @sigstore/core/dist}/asn1/dump.js (100%) rename node_modules/{sigstore/dist/util => @sigstore/core/dist}/asn1/error.js (100%) rename node_modules/{sigstore/dist/util => @sigstore/core/dist}/asn1/index.js (100%) rename node_modules/{sigstore/dist/util => @sigstore/core/dist}/asn1/length.js (100%) rename node_modules/{sigstore/dist/util => @sigstore/core/dist}/asn1/obj.js (100%) rename node_modules/{sigstore/dist/util => @sigstore/core/dist}/asn1/parse.js (99%) rename node_modules/{sigstore/dist/util => @sigstore/core/dist}/asn1/tag.js (100%) rename node_modules/{sigstore/dist/util => @sigstore/core/dist}/crypto.js (74%) rename node_modules/@sigstore/{sign/dist/util => core/dist}/dsse.js (79%) rename node_modules/@sigstore/{sign/dist/util => core/dist}/encoding.js (100%) rename node_modules/{sigstore/dist/util => @sigstore/core/dist}/index.js (62%) rename node_modules/{sigstore/dist/util => @sigstore/core/dist}/json.js (100%) create mode 100644 node_modules/@sigstore/core/dist/oid.js rename node_modules/{sigstore/dist/util => @sigstore/core/dist}/pem.js (97%) rename node_modules/{sigstore/dist/types/utility.js => @sigstore/core/dist/rfc3161/error.js} (72%) rename node_modules/@sigstore/{sign/dist/util/pem.js => core/dist/rfc3161/index.js} (64%) create mode 100644 node_modules/@sigstore/core/dist/rfc3161/timestamp.js create mode 100644 node_modules/@sigstore/core/dist/rfc3161/tstinfo.js rename node_modules/{sigstore/dist/util => @sigstore/core/dist}/stream.js (100%) rename node_modules/{sigstore => @sigstore/core}/dist/x509/cert.js (56%) rename node_modules/{sigstore => @sigstore/core}/dist/x509/ext.js (80%) rename node_modules/@sigstore/{sign/dist/util/crypto.js => core/dist/x509/index.js} (54%) rename node_modules/{sigstore => @sigstore/core}/dist/x509/sct.js (62%) create mode 100644 node_modules/@sigstore/core/package.json delete mode 100644 node_modules/@sigstore/sign/dist/util/json.js create mode 100644 node_modules/@sigstore/verify/dist/bundle/dsse.js create mode 100644 node_modules/@sigstore/verify/dist/bundle/index.js create mode 100644 node_modules/@sigstore/verify/dist/bundle/message.js rename node_modules/{sigstore => @sigstore/verify}/dist/error.js (92%) create mode 100644 node_modules/@sigstore/verify/dist/index.js rename node_modules/{sigstore/dist/x509/verify.js => @sigstore/verify/dist/key/certificate.js} (71%) create mode 100644 node_modules/@sigstore/verify/dist/key/index.js create mode 100644 node_modules/@sigstore/verify/dist/key/sct.js create mode 100644 node_modules/@sigstore/verify/dist/policy.js rename node_modules/{sigstore/dist/types/fetch.js => @sigstore/verify/dist/shared.types.js} (100%) rename node_modules/{sigstore/dist/tlog/verify => @sigstore/verify/dist/timestamp}/checkpoint.js (59%) create mode 100644 node_modules/@sigstore/verify/dist/timestamp/index.js rename node_modules/{sigstore/dist/tlog/verify => @sigstore/verify/dist/timestamp}/merkle.js (76%) create mode 100644 node_modules/@sigstore/verify/dist/timestamp/set.js create mode 100644 node_modules/@sigstore/verify/dist/timestamp/tsa.js create mode 100644 node_modules/@sigstore/verify/dist/tlog/dsse.js create mode 100644 node_modules/@sigstore/verify/dist/tlog/hashedrekord.js create mode 100644 node_modules/@sigstore/verify/dist/tlog/index.js create mode 100644 node_modules/@sigstore/verify/dist/tlog/intoto.js create mode 100644 node_modules/@sigstore/verify/dist/trust/filter.js create mode 100644 node_modules/@sigstore/verify/dist/trust/index.js create mode 100644 node_modules/@sigstore/verify/dist/trust/trust.types.js create mode 100644 node_modules/@sigstore/verify/dist/verifier.js create mode 100644 node_modules/@sigstore/verify/package.json delete mode 100644 node_modules/sigstore/dist/ca/verify/chain.js delete mode 100644 node_modules/sigstore/dist/ca/verify/index.js delete mode 100644 node_modules/sigstore/dist/ca/verify/sct.js delete mode 100644 node_modules/sigstore/dist/ca/verify/signer.js delete mode 100644 node_modules/sigstore/dist/tlog/verify/body.js delete mode 100644 node_modules/sigstore/dist/tlog/verify/index.js delete mode 100644 node_modules/sigstore/dist/tlog/verify/set.js delete mode 100644 node_modules/sigstore/dist/types/sigstore.js delete mode 100644 node_modules/sigstore/dist/util/dsse.js delete mode 100644 node_modules/sigstore/dist/util/encoding.js delete mode 100644 node_modules/sigstore/dist/verify.js diff --git a/DEPENDENCIES.md b/DEPENDENCIES.md index 5e66d51c3f047..4414b66e9c66d 100644 --- a/DEPENDENCIES.md +++ b/DEPENDENCIES.md @@ -757,15 +757,21 @@ graph LR; semver-->lru-cache; shebang-command-->shebang-regex; sigstore-->sigstore-bundle["@sigstore/bundle"]; + sigstore-->sigstore-core["@sigstore/core"]; sigstore-->sigstore-protobuf-specs["@sigstore/protobuf-specs"]; sigstore-->sigstore-sign["@sigstore/sign"]; sigstore-->sigstore-tuf["@sigstore/tuf"]; + sigstore-->sigstore-verify["@sigstore/verify"]; sigstore-bundle-->sigstore-protobuf-specs["@sigstore/protobuf-specs"]; sigstore-sign-->make-fetch-happen; sigstore-sign-->sigstore-bundle["@sigstore/bundle"]; + sigstore-sign-->sigstore-core["@sigstore/core"]; sigstore-sign-->sigstore-protobuf-specs["@sigstore/protobuf-specs"]; sigstore-tuf-->sigstore-protobuf-specs["@sigstore/protobuf-specs"]; sigstore-tuf-->tuf-js; + sigstore-verify-->sigstore-bundle["@sigstore/bundle"]; + sigstore-verify-->sigstore-core["@sigstore/core"]; + sigstore-verify-->sigstore-protobuf-specs["@sigstore/protobuf-specs"]; socks-->ip; socks-->smart-buffer; socks-proxy-agent-->agent-base; diff --git a/node_modules/.gitignore b/node_modules/.gitignore index ccc6cde538c77..4faee9d5675e8 100644 --- a/node_modules/.gitignore +++ b/node_modules/.gitignore @@ -38,9 +38,11 @@ !/@sigstore/ /@sigstore/* !/@sigstore/bundle +!/@sigstore/core !/@sigstore/protobuf-specs !/@sigstore/sign !/@sigstore/tuf +!/@sigstore/verify !/@tufjs/ /@tufjs/* !/@tufjs/canonical-json diff --git a/node_modules/@sigstore/bundle/dist/serialized.js b/node_modules/@sigstore/bundle/dist/serialized.js index f1073358cacfd..c05961a5bde2a 100644 --- a/node_modules/@sigstore/bundle/dist/serialized.js +++ b/node_modules/@sigstore/bundle/dist/serialized.js @@ -17,10 +17,17 @@ See the License for the specific language governing permissions and limitations under the License. */ const protobuf_specs_1 = require("@sigstore/protobuf-specs"); +const bundle_1 = require("./bundle"); const validate_1 = require("./validate"); const bundleFromJSON = (obj) => { const bundle = protobuf_specs_1.Bundle.fromJSON(obj); (0, validate_1.assertBundle)(bundle); + if (bundle.mediaType === bundle_1.BUNDLE_V01_MEDIA_TYPE) { + (0, validate_1.assertBundleV01)(bundle); + } + else { + (0, validate_1.assertBundleLatest)(bundle); + } return bundle; }; exports.bundleFromJSON = bundleFromJSON; diff --git a/node_modules/@sigstore/bundle/package.json b/node_modules/@sigstore/bundle/package.json index 7e26efa11a21d..152271bdf3ef1 100644 --- a/node_modules/@sigstore/bundle/package.json +++ b/node_modules/@sigstore/bundle/package.json @@ -1,6 +1,6 @@ { "name": "@sigstore/bundle", - "version": "2.1.0", + "version": "2.1.1", "description": "Sigstore bundle type", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/node_modules/@sigstore/core/LICENSE b/node_modules/@sigstore/core/LICENSE new file mode 100644 index 0000000000000..e9e7c1679a09d --- /dev/null +++ b/node_modules/@sigstore/core/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2023 The Sigstore Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/node_modules/sigstore/dist/util/asn1/dump.js b/node_modules/@sigstore/core/dist/asn1/dump.js similarity index 100% rename from node_modules/sigstore/dist/util/asn1/dump.js rename to node_modules/@sigstore/core/dist/asn1/dump.js diff --git a/node_modules/sigstore/dist/util/asn1/error.js b/node_modules/@sigstore/core/dist/asn1/error.js similarity index 100% rename from node_modules/sigstore/dist/util/asn1/error.js rename to node_modules/@sigstore/core/dist/asn1/error.js diff --git a/node_modules/sigstore/dist/util/asn1/index.js b/node_modules/@sigstore/core/dist/asn1/index.js similarity index 100% rename from node_modules/sigstore/dist/util/asn1/index.js rename to node_modules/@sigstore/core/dist/asn1/index.js diff --git a/node_modules/sigstore/dist/util/asn1/length.js b/node_modules/@sigstore/core/dist/asn1/length.js similarity index 100% rename from node_modules/sigstore/dist/util/asn1/length.js rename to node_modules/@sigstore/core/dist/asn1/length.js diff --git a/node_modules/sigstore/dist/util/asn1/obj.js b/node_modules/@sigstore/core/dist/asn1/obj.js similarity index 100% rename from node_modules/sigstore/dist/util/asn1/obj.js rename to node_modules/@sigstore/core/dist/asn1/obj.js diff --git a/node_modules/sigstore/dist/util/asn1/parse.js b/node_modules/@sigstore/core/dist/asn1/parse.js similarity index 99% rename from node_modules/sigstore/dist/util/asn1/parse.js rename to node_modules/@sigstore/core/dist/asn1/parse.js index ad50a8f1abdc2..482c7239e8316 100644 --- a/node_modules/sigstore/dist/util/asn1/parse.js +++ b/node_modules/@sigstore/core/dist/asn1/parse.js @@ -16,8 +16,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -const RE_TIME_SHORT_YEAR = /^(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})Z$/; -const RE_TIME_LONG_YEAR = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})Z$/; +const RE_TIME_SHORT_YEAR = /^(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\.\d{3})?Z$/; +const RE_TIME_LONG_YEAR = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\.\d{3})?Z$/; // Parse a BigInt from the DER-encoded buffer // https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-integer function parseInteger(buf) { diff --git a/node_modules/sigstore/dist/util/asn1/tag.js b/node_modules/@sigstore/core/dist/asn1/tag.js similarity index 100% rename from node_modules/sigstore/dist/util/asn1/tag.js rename to node_modules/@sigstore/core/dist/asn1/tag.js diff --git a/node_modules/sigstore/dist/util/crypto.js b/node_modules/@sigstore/core/dist/crypto.js similarity index 74% rename from node_modules/sigstore/dist/util/crypto.js rename to node_modules/@sigstore/core/dist/crypto.js index c26de091ecdb6..c5d899d003e1d 100644 --- a/node_modules/sigstore/dist/util/crypto.js +++ b/node_modules/@sigstore/core/dist/crypto.js @@ -3,9 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.bufferEqual = exports.randomBytes = exports.hash = exports.verifyBlob = exports.createPublicKey = void 0; +exports.bufferEqual = exports.verify = exports.hash = exports.digest = exports.createPublicKey = void 0; /* -Copyright 2022 The Sigstore Authors. +Copyright 2023 The Sigstore Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -30,7 +30,24 @@ function createPublicKey(key) { } } exports.createPublicKey = createPublicKey; -function verifyBlob(data, key, signature, algorithm) { +function digest(algorithm, ...data) { + const hash = crypto_1.default.createHash(algorithm); + for (const d of data) { + hash.update(d); + } + return hash.digest(); +} +exports.digest = digest; +// TODO: deprecate this in favor of digest() +function hash(...data) { + const hash = crypto_1.default.createHash(SHA256_ALGORITHM); + for (const d of data) { + hash.update(d); + } + return hash.digest(); +} +exports.hash = hash; +function verify(data, key, signature, algorithm) { // The try/catch is to work around an issue in Node 14.x where verify throws // an error in some scenarios if the signature is invalid. try { @@ -41,16 +58,7 @@ function verifyBlob(data, key, signature, algorithm) { return false; } } -exports.verifyBlob = verifyBlob; -function hash(data) { - const hash = crypto_1.default.createHash(SHA256_ALGORITHM); - return hash.update(data).digest(); -} -exports.hash = hash; -function randomBytes(count) { - return crypto_1.default.randomBytes(count); -} -exports.randomBytes = randomBytes; +exports.verify = verify; function bufferEqual(a, b) { try { return crypto_1.default.timingSafeEqual(a, b); diff --git a/node_modules/@sigstore/sign/dist/util/dsse.js b/node_modules/@sigstore/core/dist/dsse.js similarity index 79% rename from node_modules/@sigstore/sign/dist/util/dsse.js rename to node_modules/@sigstore/core/dist/dsse.js index befcdbdc14ec8..a78783c919a25 100644 --- a/node_modules/@sigstore/sign/dist/util/dsse.js +++ b/node_modules/@sigstore/core/dist/dsse.js @@ -19,7 +19,13 @@ limitations under the License. const PAE_PREFIX = 'DSSEv1'; // DSSE Pre-Authentication Encoding function preAuthEncoding(payloadType, payload) { - const prefix = Buffer.from(`${PAE_PREFIX} ${payloadType.length} ${payloadType} ${payload.length} `, 'ascii'); - return Buffer.concat([prefix, payload]); + const prefix = [ + PAE_PREFIX, + payloadType.length, + payloadType, + payload.length, + '', + ].join(' '); + return Buffer.concat([Buffer.from(prefix, 'ascii'), payload]); } exports.preAuthEncoding = preAuthEncoding; diff --git a/node_modules/@sigstore/sign/dist/util/encoding.js b/node_modules/@sigstore/core/dist/encoding.js similarity index 100% rename from node_modules/@sigstore/sign/dist/util/encoding.js rename to node_modules/@sigstore/core/dist/encoding.js diff --git a/node_modules/sigstore/dist/util/index.js b/node_modules/@sigstore/core/dist/index.js similarity index 62% rename from node_modules/sigstore/dist/util/index.js rename to node_modules/@sigstore/core/dist/index.js index ff4cec375af8f..ac35e86a8df7d 100644 --- a/node_modules/sigstore/dist/util/index.js +++ b/node_modules/@sigstore/core/dist/index.js @@ -23,9 +23,9 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.pem = exports.json = exports.encoding = exports.dsse = exports.crypto = exports.asn1 = void 0; +exports.X509SCTExtension = exports.X509Certificate = exports.EXTENSION_OID_SCT = exports.ByteStream = exports.RFC3161Timestamp = exports.pem = exports.json = exports.encoding = exports.dsse = exports.crypto = exports.ASN1Obj = void 0; /* -Copyright 2022 The Sigstore Authors. +Copyright 2023 The Sigstore Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -39,9 +39,18 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -exports.asn1 = __importStar(require("./asn1")); +var asn1_1 = require("./asn1"); +Object.defineProperty(exports, "ASN1Obj", { enumerable: true, get: function () { return asn1_1.ASN1Obj; } }); exports.crypto = __importStar(require("./crypto")); exports.dsse = __importStar(require("./dsse")); exports.encoding = __importStar(require("./encoding")); exports.json = __importStar(require("./json")); exports.pem = __importStar(require("./pem")); +var rfc3161_1 = require("./rfc3161"); +Object.defineProperty(exports, "RFC3161Timestamp", { enumerable: true, get: function () { return rfc3161_1.RFC3161Timestamp; } }); +var stream_1 = require("./stream"); +Object.defineProperty(exports, "ByteStream", { enumerable: true, get: function () { return stream_1.ByteStream; } }); +var x509_1 = require("./x509"); +Object.defineProperty(exports, "EXTENSION_OID_SCT", { enumerable: true, get: function () { return x509_1.EXTENSION_OID_SCT; } }); +Object.defineProperty(exports, "X509Certificate", { enumerable: true, get: function () { return x509_1.X509Certificate; } }); +Object.defineProperty(exports, "X509SCTExtension", { enumerable: true, get: function () { return x509_1.X509SCTExtension; } }); diff --git a/node_modules/sigstore/dist/util/json.js b/node_modules/@sigstore/core/dist/json.js similarity index 100% rename from node_modules/sigstore/dist/util/json.js rename to node_modules/@sigstore/core/dist/json.js index 69176ad731eb7..a50df7233c7c5 100644 --- a/node_modules/sigstore/dist/util/json.js +++ b/node_modules/@sigstore/core/dist/json.js @@ -1,6 +1,4 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.canonicalize = void 0; /* Copyright 2023 The Sigstore Authors. @@ -16,6 +14,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ +Object.defineProperty(exports, "__esModule", { value: true }); +exports.canonicalize = void 0; // JSON canonicalization per https://github.com/cyberphone/json-canonicalization // eslint-disable-next-line @typescript-eslint/no-explicit-any function canonicalize(object) { diff --git a/node_modules/@sigstore/core/dist/oid.js b/node_modules/@sigstore/core/dist/oid.js new file mode 100644 index 0000000000000..ac7a643067ad0 --- /dev/null +++ b/node_modules/@sigstore/core/dist/oid.js @@ -0,0 +1,14 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SHA2_HASH_ALGOS = exports.ECDSA_SIGNATURE_ALGOS = void 0; +exports.ECDSA_SIGNATURE_ALGOS = { + '1.2.840.10045.4.3.1': 'sha224', + '1.2.840.10045.4.3.2': 'sha256', + '1.2.840.10045.4.3.3': 'sha384', + '1.2.840.10045.4.3.4': 'sha512', +}; +exports.SHA2_HASH_ALGOS = { + '2.16.840.1.101.3.4.2.1': 'sha256', + '2.16.840.1.101.3.4.2.2': 'sha384', + '2.16.840.1.101.3.4.2.3': 'sha512', +}; diff --git a/node_modules/sigstore/dist/util/pem.js b/node_modules/@sigstore/core/dist/pem.js similarity index 97% rename from node_modules/sigstore/dist/util/pem.js rename to node_modules/@sigstore/core/dist/pem.js index 8b03b364cd7ef..f35bc3835bbd1 100644 --- a/node_modules/sigstore/dist/util/pem.js +++ b/node_modules/@sigstore/core/dist/pem.js @@ -2,7 +2,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.fromDER = exports.toDER = void 0; /* -Copyright 2022 The Sigstore Authors. +Copyright 2023 The Sigstore Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/node_modules/sigstore/dist/types/utility.js b/node_modules/@sigstore/core/dist/rfc3161/error.js similarity index 72% rename from node_modules/sigstore/dist/types/utility.js rename to node_modules/@sigstore/core/dist/rfc3161/error.js index 77c91b1923ca0..b9b549b0bb323 100644 --- a/node_modules/sigstore/dist/types/utility.js +++ b/node_modules/@sigstore/core/dist/rfc3161/error.js @@ -1,6 +1,8 @@ "use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RFC3161TimestampVerificationError = void 0; /* -Copyright 2022 The Sigstore Authors. +Copyright 2023 The Sigstore Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,4 +16,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -Object.defineProperty(exports, "__esModule", { value: true }); +class RFC3161TimestampVerificationError extends Error { +} +exports.RFC3161TimestampVerificationError = RFC3161TimestampVerificationError; diff --git a/node_modules/@sigstore/sign/dist/util/pem.js b/node_modules/@sigstore/core/dist/rfc3161/index.js similarity index 64% rename from node_modules/@sigstore/sign/dist/util/pem.js rename to node_modules/@sigstore/core/dist/rfc3161/index.js index 36eeebd2052f5..b77ecf1c7d50c 100644 --- a/node_modules/@sigstore/sign/dist/util/pem.js +++ b/node_modules/@sigstore/core/dist/rfc3161/index.js @@ -1,6 +1,4 @@ "use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.toDER = void 0; /* Copyright 2023 The Sigstore Authors. @@ -16,12 +14,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -const PEM_HEADER = /-----BEGIN (.*)-----/; -const PEM_FOOTER = /-----END (.*)-----/; -function toDER(certificate) { - const lines = certificate - .split('\n') - .map((line) => line.match(PEM_HEADER) || line.match(PEM_FOOTER) ? '' : line); - return Buffer.from(lines.join(''), 'base64'); -} -exports.toDER = toDER; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RFC3161Timestamp = void 0; +var timestamp_1 = require("./timestamp"); +Object.defineProperty(exports, "RFC3161Timestamp", { enumerable: true, get: function () { return timestamp_1.RFC3161Timestamp; } }); diff --git a/node_modules/@sigstore/core/dist/rfc3161/timestamp.js b/node_modules/@sigstore/core/dist/rfc3161/timestamp.js new file mode 100644 index 0000000000000..3e61fc1a4e169 --- /dev/null +++ b/node_modules/@sigstore/core/dist/rfc3161/timestamp.js @@ -0,0 +1,201 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.RFC3161Timestamp = void 0; +/* +Copyright 2023 The Sigstore Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +const asn1_1 = require("../asn1"); +const crypto = __importStar(require("../crypto")); +const oid_1 = require("../oid"); +const error_1 = require("./error"); +const tstinfo_1 = require("./tstinfo"); +const OID_PKCS9_CONTENT_TYPE_SIGNED_DATA = '1.2.840.113549.1.7.2'; +const OID_PKCS9_CONTENT_TYPE_TSTINFO = '1.2.840.113549.1.9.16.1.4'; +const OID_PKCS9_MESSAGE_DIGEST_KEY = '1.2.840.113549.1.9.4'; +class RFC3161Timestamp { + constructor(asn1) { + this.root = asn1; + } + static parse(der) { + const asn1 = asn1_1.ASN1Obj.parseBuffer(der); + return new RFC3161Timestamp(asn1); + } + get status() { + return this.pkiStatusInfoObj.subs[0].toInteger(); + } + get contentType() { + return this.contentTypeObj.toOID(); + } + get eContentType() { + return this.eContentTypeObj.toOID(); + } + get signingTime() { + return this.tstInfo.genTime; + } + get signerIssuer() { + return this.signerSidObj.subs[0].value; + } + get signerSerialNumber() { + return this.signerSidObj.subs[1].value; + } + get signerDigestAlgorithm() { + const oid = this.signerDigestAlgorithmObj.subs[0].toOID(); + return oid_1.SHA2_HASH_ALGOS[oid]; + } + get signatureAlgorithm() { + const oid = this.signatureAlgorithmObj.subs[0].toOID(); + return oid_1.ECDSA_SIGNATURE_ALGOS[oid]; + } + get signatureValue() { + return this.signatureValueObj.value; + } + get tstInfo() { + // Need to unpack tstInfo from an OCTET STRING + return new tstinfo_1.TSTInfo(this.eContentObj.subs[0].subs[0]); + } + verify(data, publicKey) { + if (!this.timeStampTokenObj) { + throw new error_1.RFC3161TimestampVerificationError('timeStampToken is missing'); + } + // Check for expected ContentInfo content type + if (this.contentType !== OID_PKCS9_CONTENT_TYPE_SIGNED_DATA) { + throw new error_1.RFC3161TimestampVerificationError(`incorrect content type: ${this.contentType}`); + } + // Check for expected encapsulated content type + if (this.eContentType !== OID_PKCS9_CONTENT_TYPE_TSTINFO) { + throw new error_1.RFC3161TimestampVerificationError(`incorrect encapsulated content type: ${this.eContentType}`); + } + // Check that the tstInfo references the correct artifact + this.tstInfo.verify(data); + // Check that the signed message digest matches the tstInfo + this.verifyMessageDigest(); + // Check that the signature is valid for the signed attributes + this.verifySignature(publicKey); + } + verifyMessageDigest() { + // Check that the tstInfo matches the signed data + const tstInfoDigest = crypto.digest(this.signerDigestAlgorithm, this.tstInfo.raw); + const expectedDigest = this.messageDigestAttributeObj.subs[1].subs[0].value; + if (!crypto.bufferEqual(tstInfoDigest, expectedDigest)) { + throw new error_1.RFC3161TimestampVerificationError('signed data does not match tstInfo'); + } + } + verifySignature(key) { + // Encode the signed attributes for verification + const signedAttrs = this.signedAttrsObj.toDER(); + signedAttrs[0] = 0x31; // Change context-specific tag to SET + // Check that the signature is valid for the signed attributes + const verified = crypto.verify(signedAttrs, key, this.signatureValue, this.signatureAlgorithm); + if (!verified) { + throw new error_1.RFC3161TimestampVerificationError('signature verification failed'); + } + } + // https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2 + get pkiStatusInfoObj() { + // pkiStatusInfo is the first element of the timestamp response sequence + return this.root.subs[0]; + } + // https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2 + get timeStampTokenObj() { + // timeStampToken is the first element of the timestamp response sequence + return this.root.subs[1]; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-3 + get contentTypeObj() { + return this.timeStampTokenObj.subs[0]; + } + // https://www.rfc-editor.org/rfc/rfc5652#section-3 + get signedDataObj() { + const obj = this.timeStampTokenObj.subs.find((sub) => sub.tag.isContextSpecific(0x00)); + return obj.subs[0]; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.1 + get encapContentInfoObj() { + return this.signedDataObj.subs[2]; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.1 + get signerInfosObj() { + // SignerInfos is the last element of the signed data sequence + const sd = this.signedDataObj; + return sd.subs[sd.subs.length - 1]; + } + // https://www.rfc-editor.org/rfc/rfc5652#section-5.1 + get signerInfoObj() { + // Only supporting one signer + return this.signerInfosObj.subs[0]; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.2 + get eContentTypeObj() { + return this.encapContentInfoObj.subs[0]; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.2 + get eContentObj() { + return this.encapContentInfoObj.subs[1]; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.3 + get signedAttrsObj() { + const signedAttrs = this.signerInfoObj.subs.find((sub) => sub.tag.isContextSpecific(0x00)); + return signedAttrs; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.3 + get messageDigestAttributeObj() { + const messageDigest = this.signedAttrsObj.subs.find((sub) => sub.subs[0].tag.isOID() && + sub.subs[0].toOID() === OID_PKCS9_MESSAGE_DIGEST_KEY); + return messageDigest; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.3 + get signerSidObj() { + return this.signerInfoObj.subs[1]; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.3 + get signerDigestAlgorithmObj() { + // Signature is the 2nd element of the signerInfoObj object + return this.signerInfoObj.subs[2]; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.3 + get signatureAlgorithmObj() { + // Signature is the 4th element of the signerInfoObj object + return this.signerInfoObj.subs[4]; + } + // https://datatracker.ietf.org/doc/html/rfc5652#section-5.3 + get signatureValueObj() { + // Signature is the 6th element of the signerInfoObj object + return this.signerInfoObj.subs[5]; + } +} +exports.RFC3161Timestamp = RFC3161Timestamp; diff --git a/node_modules/@sigstore/core/dist/rfc3161/tstinfo.js b/node_modules/@sigstore/core/dist/rfc3161/tstinfo.js new file mode 100644 index 0000000000000..dc8e4fb339383 --- /dev/null +++ b/node_modules/@sigstore/core/dist/rfc3161/tstinfo.js @@ -0,0 +1,61 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.TSTInfo = void 0; +const crypto = __importStar(require("../crypto")); +const oid_1 = require("../oid"); +const error_1 = require("./error"); +class TSTInfo { + constructor(asn1) { + this.root = asn1; + } + get version() { + return this.root.subs[0].toInteger(); + } + get genTime() { + return this.root.subs[4].toDate(); + } + get messageImprintHashAlgorithm() { + const oid = this.messageImprintObj.subs[0].subs[0].toOID(); + return oid_1.SHA2_HASH_ALGOS[oid]; + } + get messageImprintHashedMessage() { + return this.messageImprintObj.subs[1].value; + } + get raw() { + return this.root.toDER(); + } + verify(data) { + const digest = crypto.digest(this.messageImprintHashAlgorithm, data); + if (!crypto.bufferEqual(digest, this.messageImprintHashedMessage)) { + throw new error_1.RFC3161TimestampVerificationError('message imprint does not match artifact'); + } + } + // https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2 + get messageImprintObj() { + return this.root.subs[2]; + } +} +exports.TSTInfo = TSTInfo; diff --git a/node_modules/sigstore/dist/util/stream.js b/node_modules/@sigstore/core/dist/stream.js similarity index 100% rename from node_modules/sigstore/dist/util/stream.js rename to node_modules/@sigstore/core/dist/stream.js diff --git a/node_modules/sigstore/dist/x509/cert.js b/node_modules/@sigstore/core/dist/x509/cert.js similarity index 56% rename from node_modules/sigstore/dist/x509/cert.js rename to node_modules/@sigstore/core/dist/x509/cert.js index ec14b5f47369d..16c0c40d858d8 100644 --- a/node_modules/sigstore/dist/x509/cert.js +++ b/node_modules/@sigstore/core/dist/x509/cert.js @@ -1,40 +1,63 @@ "use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; Object.defineProperty(exports, "__esModule", { value: true }); -exports.x509Certificate = void 0; -const util_1 = require("../util"); -const asn1_1 = require("../util/asn1"); -const stream_1 = require("../util/stream"); +exports.X509Certificate = exports.EXTENSION_OID_SCT = void 0; +/* +Copyright 2023 The Sigstore Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +const asn1_1 = require("../asn1"); +const crypto = __importStar(require("../crypto")); +const oid_1 = require("../oid"); +const pem = __importStar(require("../pem")); const ext_1 = require("./ext"); const EXTENSION_OID_SUBJECT_KEY_ID = '2.5.29.14'; const EXTENSION_OID_KEY_USAGE = '2.5.29.15'; const EXTENSION_OID_SUBJECT_ALT_NAME = '2.5.29.17'; const EXTENSION_OID_BASIC_CONSTRAINTS = '2.5.29.19'; const EXTENSION_OID_AUTHORITY_KEY_ID = '2.5.29.35'; -const EXTENSION_OID_SCT = '1.3.6.1.4.1.11129.2.4.2'; -// List of recognized critical extensions -// https://www.rfc-editor.org/rfc/rfc5280#section-4.2 -const RECOGNIZED_EXTENSIONS = [ - EXTENSION_OID_KEY_USAGE, - EXTENSION_OID_BASIC_CONSTRAINTS, - EXTENSION_OID_SUBJECT_ALT_NAME, -]; -const ECDSA_SIGNATURE_ALGOS = { - '1.2.840.10045.4.3.1': 'sha224', - '1.2.840.10045.4.3.2': 'sha256', - '1.2.840.10045.4.3.3': 'sha384', - '1.2.840.10045.4.3.4': 'sha512', -}; -class x509Certificate { +exports.EXTENSION_OID_SCT = '1.3.6.1.4.1.11129.2.4.2'; +class X509Certificate { constructor(asn1) { this.root = asn1; - if (!this.checkRecognizedExtensions()) { - throw new Error('Certificate contains unrecognized critical extensions'); - } } static parse(cert) { - const der = typeof cert === 'string' ? util_1.pem.toDER(cert) : cert; + const der = typeof cert === 'string' ? pem.toDER(cert) : cert; const asn1 = asn1_1.ASN1Obj.parseBuffer(der); - return new x509Certificate(asn1); + return new X509Certificate(asn1); } get tbsCertificate() { return this.tbsCertificateObj; @@ -44,6 +67,9 @@ class x509Certificate { const ver = this.versionObj.subs[0].toInteger(); return `v${(ver + BigInt(1)).toString()}`; } + get serialNumber() { + return this.serialNumberObj.value; + } get notBefore() { // notBefore is the first element of the validity sequence return this.validityObj.subs[0].toDate(); @@ -63,41 +89,47 @@ class x509Certificate { } get signatureAlgorithm() { const oid = this.signatureAlgorithmObj.subs[0].toOID(); - return ECDSA_SIGNATURE_ALGOS[oid]; + return oid_1.ECDSA_SIGNATURE_ALGOS[oid]; } get signatureValue() { // Signature value is a bit string, so we need to skip the first byte return this.signatureValueObj.value.subarray(1); } + get subjectAltName() { + const ext = this.extSubjectAltName; + return ext?.uri || ext?.rfc822Name; + } get extensions() { // The extension list is the first (and only) element of the extensions // context specific tag const extSeq = this.extensionsObj?.subs[0]; - return extSeq?.subs || []; + return extSeq?.subs || /* istanbul ignore next */ []; } get extKeyUsage() { const ext = this.findExtension(EXTENSION_OID_KEY_USAGE); - return ext ? new ext_1.x509KeyUsageExtension(ext) : undefined; + return ext ? new ext_1.X509KeyUsageExtension(ext) : undefined; } get extBasicConstraints() { const ext = this.findExtension(EXTENSION_OID_BASIC_CONSTRAINTS); - return ext ? new ext_1.x509BasicConstraintsExtension(ext) : undefined; + return ext ? new ext_1.X509BasicConstraintsExtension(ext) : undefined; } get extSubjectAltName() { const ext = this.findExtension(EXTENSION_OID_SUBJECT_ALT_NAME); - return ext ? new ext_1.x509SubjectAlternativeNameExtension(ext) : undefined; + return ext ? new ext_1.X509SubjectAlternativeNameExtension(ext) : undefined; } get extAuthorityKeyID() { const ext = this.findExtension(EXTENSION_OID_AUTHORITY_KEY_ID); - return ext ? new ext_1.x509AuthorityKeyIDExtension(ext) : undefined; + return ext ? new ext_1.X509AuthorityKeyIDExtension(ext) : undefined; } get extSubjectKeyID() { const ext = this.findExtension(EXTENSION_OID_SUBJECT_KEY_ID); - return ext ? new ext_1.x509SubjectKeyIDExtension(ext) : undefined; + return ext + ? new ext_1.X509SubjectKeyIDExtension(ext) + : /* istanbul ignore next */ undefined; } get extSCT() { - const ext = this.findExtension(EXTENSION_OID_SCT); - return ext ? new ext_1.x509SCTExtension(ext) : undefined; + const ext = this.findExtension(exports.EXTENSION_OID_SCT); + return ext ? new ext_1.X509SCTExtension(ext) : undefined; } get isCA() { const ca = this.extBasicConstraints?.isCA || false; @@ -109,13 +141,13 @@ class x509Certificate { } extension(oid) { const ext = this.findExtension(oid); - return ext ? new ext_1.x509Extension(ext) : undefined; + return ext ? new ext_1.X509Extension(ext) : undefined; } verify(issuerCertificate) { // Use the issuer's public key if provided, otherwise use the subject's const publicKey = issuerCertificate?.publicKey || this.publicKey; - const key = util_1.crypto.createPublicKey(publicKey); - return util_1.crypto.verifyBlob(this.tbsCertificate.toDER(), key, this.signatureValue, this.signatureAlgorithm); + const key = crypto.createPublicKey(publicKey); + return crypto.verify(this.tbsCertificate.toDER(), key, this.signatureValue, this.signatureAlgorithm); } validForDate(date) { return this.notBefore <= date && date <= this.notAfter; @@ -123,71 +155,18 @@ class x509Certificate { equals(other) { return this.root.toDER().equals(other.root.toDER()); } - verifySCTs(issuer, logs) { - let extSCT; - // Verifying the SCT requires that we remove the SCT extension and - // re-encode the TBS structure to DER -- this value is part of the data - // over which the signature is calculated. Since this is a destructive action - // we create a copy of the certificate so we can remove the SCT extension - // without affecting the original certificate. - const clone = this.clone(); - // Intentionally not using the findExtension method here because we want to - // remove the the SCT extension from the certificate before calculating the - // PreCert structure - for (let i = 0; i < clone.extensions.length; i++) { - const ext = clone.extensions[i]; - if (ext.subs[0].toOID() === EXTENSION_OID_SCT) { - extSCT = new ext_1.x509SCTExtension(ext); - // Remove the extension from the certificate - clone.extensions.splice(i, 1); - break; - } - } - if (!extSCT) { - throw new Error('Certificate does not contain SCT extension'); - } - if (extSCT?.signedCertificateTimestamps?.length === 0) { - throw new Error('Certificate does not contain any SCTs'); - } - // Construct the PreCert structure - // https://www.rfc-editor.org/rfc/rfc6962#section-3.2 - const preCert = new stream_1.ByteStream(); - // Calculate hash of the issuer's public key - const issuerId = util_1.crypto.hash(issuer.publicKey); - preCert.appendView(issuerId); - // Re-encodes the certificate to DER after removing the SCT extension - const tbs = clone.tbsCertificate.toDER(); - preCert.appendUint24(tbs.length); - preCert.appendView(tbs); - // Calculate and return the verification results for each SCT - return extSCT.signedCertificateTimestamps.map((sct) => ({ - logID: sct.logID, - verified: sct.verify(preCert.buffer, logs), - })); - } // Creates a copy of the certificate with a new buffer clone() { const der = this.root.toDER(); const clone = Buffer.alloc(der.length); der.copy(clone); - return x509Certificate.parse(clone); + return X509Certificate.parse(clone); } findExtension(oid) { // Find the extension with the given OID. The OID will always be the first // element of the extension sequence return this.extensions.find((ext) => ext.subs[0].toOID() === oid); } - // A certificate should be considered invalid if it contains critical - // extensions that are not recognized - checkRecognizedExtensions() { - // The extension list is the first (and only) element of the extensions - // context specific tag - const extSeq = this.extensionsObj?.subs[0]; - const exts = extSeq?.subs.map((ext) => new ext_1.x509Extension(ext)); - // Check for unrecognized critical extensions - return (!exts || - exts.every((ext) => !ext.critical || RECOGNIZED_EXTENSIONS.includes(ext.oid))); - } ///////////////////////////////////////////////////////////////////////////// // The following properties use the documented x509 structure to locate the // desired ASN.1 object @@ -212,6 +191,11 @@ class x509Certificate { // version is the first element of the tbsCertificate sequence return this.tbsCertificateObj.subs[0]; } + // https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.2 + get serialNumberObj() { + // serialNumber is the second element of the tbsCertificate sequence + return this.tbsCertificateObj.subs[1]; + } // https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.4 get issuerObj() { // issuer is the fourth element of the tbsCertificate sequence @@ -239,4 +223,4 @@ class x509Certificate { return this.tbsCertificateObj.subs.find((sub) => sub.tag.isContextSpecific(0x03)); } } -exports.x509Certificate = x509Certificate; +exports.X509Certificate = X509Certificate; diff --git a/node_modules/sigstore/dist/x509/ext.js b/node_modules/@sigstore/core/dist/x509/ext.js similarity index 80% rename from node_modules/sigstore/dist/x509/ext.js rename to node_modules/@sigstore/core/dist/x509/ext.js index 246aeb095802f..1d481261b0aa6 100644 --- a/node_modules/sigstore/dist/x509/ext.js +++ b/node_modules/@sigstore/core/dist/x509/ext.js @@ -1,10 +1,10 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.x509SCTExtension = exports.x509SubjectKeyIDExtension = exports.x509AuthorityKeyIDExtension = exports.x509SubjectAlternativeNameExtension = exports.x509KeyUsageExtension = exports.x509BasicConstraintsExtension = exports.x509Extension = void 0; -const stream_1 = require("../util/stream"); +exports.X509SCTExtension = exports.X509SubjectKeyIDExtension = exports.X509AuthorityKeyIDExtension = exports.X509SubjectAlternativeNameExtension = exports.X509KeyUsageExtension = exports.X509BasicConstraintsExtension = exports.X509Extension = void 0; +const stream_1 = require("../stream"); const sct_1 = require("./sct"); // https://www.rfc-editor.org/rfc/rfc5280#section-4.1 -class x509Extension { +class X509Extension { constructor(asn1) { this.root = asn1; } @@ -27,11 +27,11 @@ class x509Extension { return this.root.subs[this.root.subs.length - 1]; } } -exports.x509Extension = x509Extension; +exports.X509Extension = X509Extension; // https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.9 -class x509BasicConstraintsExtension extends x509Extension { +class X509BasicConstraintsExtension extends X509Extension { get isCA() { - return this.sequence.subs[0].toBoolean(); + return this.sequence.subs[0]?.toBoolean() ?? false; } get pathLenConstraint() { return this.sequence.subs.length > 1 @@ -44,9 +44,9 @@ class x509BasicConstraintsExtension extends x509Extension { return this.extnValueObj.subs[0]; } } -exports.x509BasicConstraintsExtension = x509BasicConstraintsExtension; +exports.X509BasicConstraintsExtension = X509BasicConstraintsExtension; // https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.3 -class x509KeyUsageExtension extends x509Extension { +class X509KeyUsageExtension extends X509Extension { get digitalSignature() { return this.bitString[0] === 1; } @@ -62,9 +62,9 @@ class x509KeyUsageExtension extends x509Extension { return this.extnValueObj.subs[0].toBitString(); } } -exports.x509KeyUsageExtension = x509KeyUsageExtension; +exports.X509KeyUsageExtension = X509KeyUsageExtension; // https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.6 -class x509SubjectAlternativeNameExtension extends x509Extension { +class X509SubjectAlternativeNameExtension extends X509Extension { get rfc822Name() { return this.findGeneralName(0x01)?.value.toString('ascii'); } @@ -95,9 +95,9 @@ class x509SubjectAlternativeNameExtension extends x509Extension { return this.extnValueObj.subs[0].subs; } } -exports.x509SubjectAlternativeNameExtension = x509SubjectAlternativeNameExtension; +exports.X509SubjectAlternativeNameExtension = X509SubjectAlternativeNameExtension; // https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.1 -class x509AuthorityKeyIDExtension extends x509Extension { +class X509AuthorityKeyIDExtension extends X509Extension { get keyIdentifier() { return this.findSequenceMember(0x00)?.value; } @@ -109,16 +109,16 @@ class x509AuthorityKeyIDExtension extends x509Extension { return this.extnValueObj.subs[0]; } } -exports.x509AuthorityKeyIDExtension = x509AuthorityKeyIDExtension; +exports.X509AuthorityKeyIDExtension = X509AuthorityKeyIDExtension; // https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.2 -class x509SubjectKeyIDExtension extends x509Extension { +class X509SubjectKeyIDExtension extends X509Extension { get keyIdentifier() { return this.extnValueObj.subs[0].value; } } -exports.x509SubjectKeyIDExtension = x509SubjectKeyIDExtension; +exports.X509SubjectKeyIDExtension = X509SubjectKeyIDExtension; // https://www.rfc-editor.org/rfc/rfc6962#section-3.3 -class x509SCTExtension extends x509Extension { +class X509SCTExtension extends X509Extension { constructor(asn1) { super(asn1); } @@ -142,4 +142,4 @@ class x509SCTExtension extends x509Extension { return sctList; } } -exports.x509SCTExtension = x509SCTExtension; +exports.X509SCTExtension = X509SCTExtension; diff --git a/node_modules/@sigstore/sign/dist/util/crypto.js b/node_modules/@sigstore/core/dist/x509/index.js similarity index 54% rename from node_modules/@sigstore/sign/dist/util/crypto.js rename to node_modules/@sigstore/core/dist/x509/index.js index 11aad2fb6ff8b..cdd77e58f37d5 100644 --- a/node_modules/@sigstore/sign/dist/util/crypto.js +++ b/node_modules/@sigstore/core/dist/x509/index.js @@ -1,9 +1,4 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.hash = void 0; /* Copyright 2023 The Sigstore Authors. @@ -19,9 +14,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -const crypto_1 = __importDefault(require("crypto")); -const SHA256_ALGORITHM = 'sha256'; -function hash(data, algorithm = SHA256_ALGORITHM) { - return crypto_1.default.createHash(algorithm).update(data).digest(); -} -exports.hash = hash; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.X509SCTExtension = exports.X509Certificate = exports.EXTENSION_OID_SCT = void 0; +var cert_1 = require("./cert"); +Object.defineProperty(exports, "EXTENSION_OID_SCT", { enumerable: true, get: function () { return cert_1.EXTENSION_OID_SCT; } }); +Object.defineProperty(exports, "X509Certificate", { enumerable: true, get: function () { return cert_1.X509Certificate; } }); +var ext_1 = require("./ext"); +Object.defineProperty(exports, "X509SCTExtension", { enumerable: true, get: function () { return ext_1.X509SCTExtension; } }); diff --git a/node_modules/sigstore/dist/x509/sct.js b/node_modules/@sigstore/core/dist/x509/sct.js similarity index 62% rename from node_modules/sigstore/dist/x509/sct.js rename to node_modules/@sigstore/core/dist/x509/sct.js index 72528dd3a2077..1603059c0d1ac 100644 --- a/node_modules/sigstore/dist/x509/sct.js +++ b/node_modules/@sigstore/core/dist/x509/sct.js @@ -1,8 +1,46 @@ "use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; Object.defineProperty(exports, "__esModule", { value: true }); exports.SignedCertificateTimestamp = void 0; -const util_1 = require("../util"); -const stream_1 = require("../util/stream"); +/* +Copyright 2023 The Sigstore Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +const crypto = __importStar(require("../crypto")); +const stream_1 = require("../stream"); class SignedCertificateTimestamp { constructor(options) { this.version = options.version; @@ -20,31 +58,32 @@ class SignedCertificateTimestamp { // https://www.rfc-editor.org/rfc/rfc5246#section-7.4.1.4.1 get algorithm() { switch (this.hashAlgorithm) { + /* istanbul ignore next */ case 0: return 'none'; + /* istanbul ignore next */ case 1: return 'md5'; + /* istanbul ignore next */ case 2: return 'sha1'; + /* istanbul ignore next */ case 3: return 'sha224'; case 4: return 'sha256'; + /* istanbul ignore next */ case 5: return 'sha384'; + /* istanbul ignore next */ case 6: return 'sha512'; + /* istanbul ignore next */ default: return 'unknown'; } } - verify(preCert, logs) { - // Find key for the log reponsible for this signature - const log = logs.find((log) => log.logId?.keyId.equals(this.logID)); - if (!log?.publicKey?.rawBytes) { - throw new Error(`No key found for log: ${this.logID.toString('base64')}`); - } - const publicKey = util_1.crypto.createPublicKey(log.publicKey.rawBytes); + verify(preCert, key) { // Assemble the digitally-signed struct (the data over which the signature // was generated). // https://www.rfc-editor.org/rfc/rfc6962#section-3.2 @@ -55,10 +94,11 @@ class SignedCertificateTimestamp { stream.appendUint16(0x01); // LogEntryType = precert_entry(1) stream.appendView(preCert); stream.appendUint16(this.extensions.byteLength); + /* istanbul ignore next - extensions are very uncommon */ if (this.extensions.byteLength > 0) { stream.appendView(this.extensions); } - return util_1.crypto.verifyBlob(stream.buffer, publicKey, this.signature, this.algorithm); + return crypto.verify(stream.buffer, key, this.signature, this.algorithm); } // Parses a SignedCertificateTimestamp from a buffer. SCTs are encoded using // TLS encoding which means the fields and lengths of most fields are diff --git a/node_modules/@sigstore/core/package.json b/node_modules/@sigstore/core/package.json new file mode 100644 index 0000000000000..08a32034766a5 --- /dev/null +++ b/node_modules/@sigstore/core/package.json @@ -0,0 +1,31 @@ +{ + "name": "@sigstore/core", + "version": "0.2.0", + "description": "Base library for Sigstore", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "clean": "shx rm -rf dist *.tsbuildinfo", + "build": "tsc --build", + "test": "jest" + }, + "files": [ + "dist" + ], + "author": "bdehamer@github.com", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "git+https://github.com/sigstore/sigstore-js.git" + }, + "bugs": { + "url": "https://github.com/sigstore/sigstore-js/issues" + }, + "homepage": "https://github.com/sigstore/sigstore-js/tree/main/packages/core#readme", + "publishConfig": { + "provenance": true + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } +} diff --git a/node_modules/@sigstore/sign/dist/util/index.js b/node_modules/@sigstore/sign/dist/util/index.js index 567e5dbf6e04c..f467c9150c348 100644 --- a/node_modules/@sigstore/sign/dist/util/index.js +++ b/node_modules/@sigstore/sign/dist/util/index.js @@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", { value: true }); -exports.ua = exports.pem = exports.oidc = exports.json = exports.encoding = exports.dsse = exports.crypto = void 0; +exports.ua = exports.oidc = exports.pem = exports.json = exports.encoding = exports.dsse = exports.crypto = void 0; /* Copyright 2023 The Sigstore Authors. @@ -39,10 +39,11 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -exports.crypto = __importStar(require("./crypto")); -exports.dsse = __importStar(require("./dsse")); -exports.encoding = __importStar(require("./encoding")); -exports.json = __importStar(require("./json")); +var core_1 = require("@sigstore/core"); +Object.defineProperty(exports, "crypto", { enumerable: true, get: function () { return core_1.crypto; } }); +Object.defineProperty(exports, "dsse", { enumerable: true, get: function () { return core_1.dsse; } }); +Object.defineProperty(exports, "encoding", { enumerable: true, get: function () { return core_1.encoding; } }); +Object.defineProperty(exports, "json", { enumerable: true, get: function () { return core_1.json; } }); +Object.defineProperty(exports, "pem", { enumerable: true, get: function () { return core_1.pem; } }); exports.oidc = __importStar(require("./oidc")); -exports.pem = __importStar(require("./pem")); exports.ua = __importStar(require("./ua")); diff --git a/node_modules/@sigstore/sign/dist/util/json.js b/node_modules/@sigstore/sign/dist/util/json.js deleted file mode 100644 index 69176ad731eb7..0000000000000 --- a/node_modules/@sigstore/sign/dist/util/json.js +++ /dev/null @@ -1,61 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.canonicalize = void 0; -/* -Copyright 2023 The Sigstore Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -// JSON canonicalization per https://github.com/cyberphone/json-canonicalization -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function canonicalize(object) { - let buffer = ''; - if (object === null || typeof object !== 'object' || object.toJSON != null) { - // Primitives or toJSONable objects - buffer += JSON.stringify(object); - } - else if (Array.isArray(object)) { - // Array - maintain element order - buffer += '['; - let first = true; - object.forEach((element) => { - if (!first) { - buffer += ','; - } - first = false; - // recursive call - buffer += canonicalize(element); - }); - buffer += ']'; - } - else { - // Object - Sort properties before serializing - buffer += '{'; - let first = true; - Object.keys(object) - .sort() - .forEach((property) => { - if (!first) { - buffer += ','; - } - first = false; - buffer += JSON.stringify(property); - buffer += ':'; - // recursive call - buffer += canonicalize(object[property]); - }); - buffer += '}'; - } - return buffer; -} -exports.canonicalize = canonicalize; diff --git a/node_modules/@sigstore/sign/dist/util/oidc.js b/node_modules/@sigstore/sign/dist/util/oidc.js index 8b49f3bbe8440..2f5947d7b6b87 100644 --- a/node_modules/@sigstore/sign/dist/util/oidc.js +++ b/node_modules/@sigstore/sign/dist/util/oidc.js @@ -1,27 +1,4 @@ "use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; Object.defineProperty(exports, "__esModule", { value: true }); exports.extractJWTSubject = void 0; /* @@ -39,10 +16,10 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -const enc = __importStar(require("./encoding")); +const core_1 = require("@sigstore/core"); function extractJWTSubject(jwt) { const parts = jwt.split('.', 3); - const payload = JSON.parse(enc.base64Decode(parts[1])); + const payload = JSON.parse(core_1.encoding.base64Decode(parts[1])); switch (payload.iss) { case 'https://accounts.google.com': case 'https://oauth2.sigstore.dev/auth': diff --git a/node_modules/@sigstore/sign/package.json b/node_modules/@sigstore/sign/package.json index 7075ee16aeb0d..5f330b58c1b0e 100644 --- a/node_modules/@sigstore/sign/package.json +++ b/node_modules/@sigstore/sign/package.json @@ -1,6 +1,6 @@ { "name": "@sigstore/sign", - "version": "2.2.0", + "version": "2.2.1", "description": "Sigstore signing library", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -27,12 +27,13 @@ }, "devDependencies": { "@sigstore/jest": "^0.0.0", - "@sigstore/mock": "^0.6.0", + "@sigstore/mock": "^0.6.3", "@sigstore/rekor-types": "^2.0.0", - "@types/make-fetch-happen": "^10.0.3" + "@types/make-fetch-happen": "^10.0.4" }, "dependencies": { - "@sigstore/bundle": "^2.1.0", + "@sigstore/bundle": "^2.1.1", + "@sigstore/core": "^0.2.0", "@sigstore/protobuf-specs": "^0.2.1", "make-fetch-happen": "^13.0.0" }, diff --git a/node_modules/@sigstore/verify/dist/bundle/dsse.js b/node_modules/@sigstore/verify/dist/bundle/dsse.js new file mode 100644 index 0000000000000..193f875fd1014 --- /dev/null +++ b/node_modules/@sigstore/verify/dist/bundle/dsse.js @@ -0,0 +1,43 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DSSESignatureContent = void 0; +/* +Copyright 2023 The Sigstore Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +const core_1 = require("@sigstore/core"); +class DSSESignatureContent { + constructor(env) { + this.env = env; + } + compareDigest(digest) { + return core_1.crypto.bufferEqual(digest, core_1.crypto.hash(this.env.payload)); + } + compareSignature(signature) { + return core_1.crypto.bufferEqual(signature, this.signature); + } + verifySignature(key) { + return core_1.crypto.verify(this.preAuthEncoding, key, this.signature); + } + get signature() { + return this.env.signatures.length > 0 + ? this.env.signatures[0].sig + : Buffer.from(''); + } + // DSSE Pre-Authentication Encoding + get preAuthEncoding() { + return core_1.dsse.preAuthEncoding(this.env.payloadType, this.env.payload); + } +} +exports.DSSESignatureContent = DSSESignatureContent; diff --git a/node_modules/@sigstore/verify/dist/bundle/index.js b/node_modules/@sigstore/verify/dist/bundle/index.js new file mode 100644 index 0000000000000..25f35a91d49cb --- /dev/null +++ b/node_modules/@sigstore/verify/dist/bundle/index.js @@ -0,0 +1,53 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.signatureContent = exports.toSignedEntity = void 0; +const core_1 = require("@sigstore/core"); +const dsse_1 = require("./dsse"); +const message_1 = require("./message"); +function toSignedEntity(bundle, artifact) { + const { tlogEntries, timestampVerificationData } = bundle.verificationMaterial; + const timestamps = []; + for (const entry of tlogEntries) { + timestamps.push({ + $case: 'transparency-log', + tlogEntry: entry, + }); + } + for (const ts of timestampVerificationData?.rfc3161Timestamps ?? []) { + timestamps.push({ + $case: 'timestamp-authority', + timestamp: core_1.RFC3161Timestamp.parse(ts.signedTimestamp), + }); + } + return { + signature: signatureContent(bundle, artifact), + key: key(bundle), + tlogEntries, + timestamps, + }; +} +exports.toSignedEntity = toSignedEntity; +function signatureContent(bundle, artifact) { + switch (bundle.content.$case) { + case 'dsseEnvelope': + return new dsse_1.DSSESignatureContent(bundle.content.dsseEnvelope); + case 'messageSignature': + return new message_1.MessageSignatureContent(bundle.content.messageSignature, artifact); + } +} +exports.signatureContent = signatureContent; +function key(bundle) { + switch (bundle.verificationMaterial.content.$case) { + case 'publicKey': + return { + $case: 'public-key', + hint: bundle.verificationMaterial.content.publicKey.hint, + }; + case 'x509CertificateChain': + return { + $case: 'certificate', + certificate: core_1.X509Certificate.parse(bundle.verificationMaterial.content.x509CertificateChain + .certificates[0].rawBytes), + }; + } +} diff --git a/node_modules/@sigstore/verify/dist/bundle/message.js b/node_modules/@sigstore/verify/dist/bundle/message.js new file mode 100644 index 0000000000000..836148c68a8b6 --- /dev/null +++ b/node_modules/@sigstore/verify/dist/bundle/message.js @@ -0,0 +1,36 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MessageSignatureContent = void 0; +/* +Copyright 2023 The Sigstore Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +const core_1 = require("@sigstore/core"); +class MessageSignatureContent { + constructor(messageSignature, artifact) { + this.signature = messageSignature.signature; + this.messageDigest = messageSignature.messageDigest.digest; + this.artifact = artifact; + } + compareSignature(signature) { + return core_1.crypto.bufferEqual(signature, this.signature); + } + compareDigest(digest) { + return core_1.crypto.bufferEqual(digest, this.messageDigest); + } + verifySignature(key) { + return core_1.crypto.verify(this.artifact, key, this.signature); + } +} +exports.MessageSignatureContent = MessageSignatureContent; diff --git a/node_modules/sigstore/dist/error.js b/node_modules/@sigstore/verify/dist/error.js similarity index 92% rename from node_modules/sigstore/dist/error.js rename to node_modules/@sigstore/verify/dist/error.js index b0a7dbc83f710..6cb1cd4121343 100644 --- a/node_modules/sigstore/dist/error.js +++ b/node_modules/@sigstore/verify/dist/error.js @@ -1,4 +1,6 @@ "use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.PolicyError = exports.VerificationError = void 0; /* Copyright 2023 The Sigstore Authors. @@ -14,20 +16,15 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.PolicyError = exports.VerificationError = void 0; class BaseError extends Error { constructor({ code, message, cause, }) { super(message); - this.name = this.constructor.name; this.code = code; this.cause = cause; + this.name = this.constructor.name; } } class VerificationError extends BaseError { - constructor(message) { - super({ code: 'VERIFICATION_ERROR', message }); - } } exports.VerificationError = VerificationError; class PolicyError extends BaseError { diff --git a/node_modules/@sigstore/verify/dist/index.js b/node_modules/@sigstore/verify/dist/index.js new file mode 100644 index 0000000000000..879bd3acbc5dc --- /dev/null +++ b/node_modules/@sigstore/verify/dist/index.js @@ -0,0 +1,27 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Verifier = exports.toTrustMaterial = exports.VerificationError = exports.PolicyError = exports.toSignedEntity = void 0; +/* +Copyright 2023 The Sigstore Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +var bundle_1 = require("./bundle"); +Object.defineProperty(exports, "toSignedEntity", { enumerable: true, get: function () { return bundle_1.toSignedEntity; } }); +var error_1 = require("./error"); +Object.defineProperty(exports, "PolicyError", { enumerable: true, get: function () { return error_1.PolicyError; } }); +Object.defineProperty(exports, "VerificationError", { enumerable: true, get: function () { return error_1.VerificationError; } }); +var trust_1 = require("./trust"); +Object.defineProperty(exports, "toTrustMaterial", { enumerable: true, get: function () { return trust_1.toTrustMaterial; } }); +var verifier_1 = require("./verifier"); +Object.defineProperty(exports, "Verifier", { enumerable: true, get: function () { return verifier_1.Verifier; } }); diff --git a/node_modules/sigstore/dist/x509/verify.js b/node_modules/@sigstore/verify/dist/key/certificate.js similarity index 71% rename from node_modules/sigstore/dist/x509/verify.js rename to node_modules/@sigstore/verify/dist/key/certificate.js index b4c7f39912a84..c9140dd98d58a 100644 --- a/node_modules/sigstore/dist/x509/verify.js +++ b/node_modules/@sigstore/verify/dist/key/certificate.js @@ -1,25 +1,36 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.verifyCertificateChain = void 0; -/* -Copyright 2023 The Sigstore Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ +exports.CertificateChainVerifier = exports.verifyCertificateChain = void 0; const error_1 = require("../error"); -function verifyCertificateChain(opts) { - const verifier = new CertificateChainVerifier(opts); - return verifier.verify(); +const trust_1 = require("../trust"); +function verifyCertificateChain(leaf, certificateAuthorities) { + // Filter list of trusted CAs to those which are valid for the given + // leaf certificate. + const cas = (0, trust_1.filterCertAuthorities)(certificateAuthorities, { + start: leaf.notBefore, + end: leaf.notAfter, + }); + /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ + let error; + for (const ca of cas) { + try { + const verifier = new CertificateChainVerifier({ + trustedCerts: ca.certChain, + untrustedCert: leaf, + }); + return verifier.verify(); + } + catch (err) { + error = err; + } + } + // If we failed to verify the certificate chain for all of the trusted + // CAs, throw the last error we encountered. + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'Failed to verify certificate chain', + cause: error, + }); } exports.verifyCertificateChain = verifyCertificateChain; class CertificateChainVerifier { @@ -30,7 +41,6 @@ class CertificateChainVerifier { ...opts.trustedCerts, opts.untrustedCert, ]); - this.validAt = opts.validAt || new Date(); } verify() { // Construct certificate path from leaf to root @@ -47,9 +57,13 @@ class CertificateChainVerifier { // Filter for paths which contain a trusted certificate paths = paths.filter((path) => path.some((cert) => this.trustedCerts.includes(cert))); if (paths.length === 0) { - throw new error_1.VerificationError('No trusted certificate path found'); + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'no trusted certificate path found', + }); } // Find the shortest of possible paths + /* istanbul ignore next */ const path = paths.reduce((prev, curr) => prev.length < curr.length ? prev : curr); // Construct chain from shortest path // Removes the last certificate in the path, which will be a second copy @@ -61,7 +75,10 @@ class CertificateChainVerifier { const paths = []; const issuers = this.findIssuer(certificate); if (issuers.length === 0) { - throw new error_1.VerificationError('No valid certificate path found'); + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'no valid certificate path found', + }); } for (let i = 0; i < issuers.length; i++) { const issuer = issuers[i]; @@ -119,30 +136,37 @@ class CertificateChainVerifier { return certificate.verify(issuer); } catch (ex) { + /* istanbul ignore next - should never error */ return false; } }); return issuers; } checkPath(path) { + /* istanbul ignore if */ if (path.length < 1) { - throw new error_1.VerificationError('Certificate chain must contain at least one certificate'); - } - // Check that all certificates are valid at the check date - const validForDate = path.every((cert) => cert.validForDate(this.validAt)); - if (!validForDate) { - throw new error_1.VerificationError('Certificate is not valid or expired at the specified date'); + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'certificate chain must contain at least one certificate', + }); } // Ensure that all certificates beyond the leaf are CAs const validCAs = path.slice(1).every((cert) => cert.isCA); if (!validCAs) { - throw new error_1.VerificationError('Intermediate certificate is not a CA'); + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'intermediate certificate is not a CA', + }); } // Certificate's issuer must match the subject of the next certificate // in the chain for (let i = path.length - 2; i >= 0; i--) { + /* istanbul ignore if */ if (!path[i].issuer.equals(path[i + 1].subject)) { - throw new error_1.VerificationError('Incorrect certificate name chaining'); + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'incorrect certificate name chaining', + }); } } // Check pathlength constraints @@ -157,12 +181,16 @@ class CertificateChainVerifier { // greater than or equal to it's own depth in the chain (with an // adjustment for the leaf certificate) if (pathLength !== undefined && pathLength < i - 1) { - throw new error_1.VerificationError('Path length constraint exceeded'); + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'path length constraint exceeded', + }); } } } } } +exports.CertificateChainVerifier = CertificateChainVerifier; // Remove duplicate certificates from the array function dedupeCertificates(certs) { for (let i = 0; i < certs.length; i++) { diff --git a/node_modules/@sigstore/verify/dist/key/index.js b/node_modules/@sigstore/verify/dist/key/index.js new file mode 100644 index 0000000000000..682a306803a99 --- /dev/null +++ b/node_modules/@sigstore/verify/dist/key/index.js @@ -0,0 +1,72 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyCertificate = exports.verifyPublicKey = void 0; +/* +Copyright 2023 The Sigstore Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +const core_1 = require("@sigstore/core"); +const error_1 = require("../error"); +const certificate_1 = require("./certificate"); +const sct_1 = require("./sct"); +const OID_FULCIO_ISSUER_V1 = '1.3.6.1.4.1.57264.1.1'; +const OID_FULCIO_ISSUER_V2 = '1.3.6.1.4.1.57264.1.8'; +function verifyPublicKey(hint, timestamps, trustMaterial) { + const key = trustMaterial.publicKey(hint); + timestamps.forEach((timestamp) => { + if (!key.validFor(timestamp)) { + throw new error_1.VerificationError({ + code: 'PUBLIC_KEY_ERROR', + message: `Public key is not valid for timestamp: ${timestamp.toISOString()}`, + }); + } + }); + return { key: key.publicKey }; +} +exports.verifyPublicKey = verifyPublicKey; +function verifyCertificate(leaf, timestamps, trustMaterial) { + // Check that leaf certificate chains to a trusted CA + const path = (0, certificate_1.verifyCertificateChain)(leaf, trustMaterial.certificateAuthorities); + // Check that ALL certificates are valid for ALL of the timestamps + const validForDate = timestamps.every((timestamp) => path.every((cert) => cert.validForDate(timestamp))); + if (!validForDate) { + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'certificate is not valid or expired at the specified date', + }); + } + return { + scts: (0, sct_1.verifySCTs)(path[0], path[1], trustMaterial.ctlogs), + signer: getSigner(path[0]), + }; +} +exports.verifyCertificate = verifyCertificate; +function getSigner(cert) { + let issuer; + const issuerExtension = cert.extension(OID_FULCIO_ISSUER_V2); + if (issuerExtension) { + issuer = issuerExtension.valueObj.subs?.[0]?.value.toString('ascii'); + } + else { + issuer = cert.extension(OID_FULCIO_ISSUER_V1)?.value.toString('ascii'); + } + const identity = { + extensions: { issuer }, + subjectAlternativeName: cert.subjectAltName, + }; + return { + key: core_1.crypto.createPublicKey(cert.publicKey), + identity, + }; +} diff --git a/node_modules/@sigstore/verify/dist/key/sct.js b/node_modules/@sigstore/verify/dist/key/sct.js new file mode 100644 index 0000000000000..aea412840e103 --- /dev/null +++ b/node_modules/@sigstore/verify/dist/key/sct.js @@ -0,0 +1,79 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifySCTs = void 0; +/* +Copyright 2023 The Sigstore Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +const core_1 = require("@sigstore/core"); +const error_1 = require("../error"); +const trust_1 = require("../trust"); +function verifySCTs(cert, issuer, ctlogs) { + let extSCT; + // Verifying the SCT requires that we remove the SCT extension and + // re-encode the TBS structure to DER -- this value is part of the data + // over which the signature is calculated. Since this is a destructive action + // we create a copy of the certificate so we can remove the SCT extension + // without affecting the original certificate. + const clone = cert.clone(); + // Intentionally not using the findExtension method here because we want to + // remove the the SCT extension from the certificate before calculating the + // PreCert structure + for (let i = 0; i < clone.extensions.length; i++) { + const ext = clone.extensions[i]; + if (ext.subs[0].toOID() === core_1.EXTENSION_OID_SCT) { + extSCT = new core_1.X509SCTExtension(ext); + // Remove the extension from the certificate + clone.extensions.splice(i, 1); + break; + } + } + // No SCT extension found to verify + if (!extSCT) { + return []; + } + // Found an SCT extension but it has no SCTs + /* istanbul ignore if -- too difficult to fabricate test case for this */ + if (extSCT.signedCertificateTimestamps.length === 0) { + return []; + } + // Construct the PreCert structure + // https://www.rfc-editor.org/rfc/rfc6962#section-3.2 + const preCert = new core_1.ByteStream(); + // Calculate hash of the issuer's public key + const issuerId = core_1.crypto.hash(issuer.publicKey); + preCert.appendView(issuerId); + // Re-encodes the certificate to DER after removing the SCT extension + const tbs = clone.tbsCertificate.toDER(); + preCert.appendUint24(tbs.length); + preCert.appendView(tbs); + // Calculate and return the verification results for each SCT + return extSCT.signedCertificateTimestamps.map((sct) => { + // Find the ctlog instance that corresponds to the SCT's logID + const validCTLogs = (0, trust_1.filterTLogAuthorities)(ctlogs, { + logID: sct.logID, + targetDate: sct.datetime, + }); + // See if the SCT is valid for any of the CT logs + const verified = validCTLogs.some((log) => sct.verify(preCert.buffer, log.publicKey)); + if (!verified) { + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'SCT verification failed', + }); + } + return sct.logID; + }); +} +exports.verifySCTs = verifySCTs; diff --git a/node_modules/@sigstore/verify/dist/policy.js b/node_modules/@sigstore/verify/dist/policy.js new file mode 100644 index 0000000000000..731e5c8332847 --- /dev/null +++ b/node_modules/@sigstore/verify/dist/policy.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyExtensions = exports.verifySubjectAlternativeName = void 0; +const error_1 = require("./error"); +function verifySubjectAlternativeName(policyIdentity, signerIdentity) { + if (signerIdentity === undefined || !signerIdentity.match(policyIdentity)) { + throw new error_1.PolicyError({ + code: 'UNTRUSTED_SIGNER_ERROR', + message: `certificate identity error - expected ${policyIdentity}, got ${signerIdentity}`, + }); + } +} +exports.verifySubjectAlternativeName = verifySubjectAlternativeName; +function verifyExtensions(policyExtensions, signerExtensions = {}) { + let key; + for (key in policyExtensions) { + if (signerExtensions[key] !== policyExtensions[key]) { + throw new error_1.PolicyError({ + code: 'UNTRUSTED_SIGNER_ERROR', + message: `invalid certificate extension - expected ${key}=${policyExtensions[key]}, got ${key}=${signerExtensions[key]}`, + }); + } + } +} +exports.verifyExtensions = verifyExtensions; diff --git a/node_modules/sigstore/dist/types/fetch.js b/node_modules/@sigstore/verify/dist/shared.types.js similarity index 100% rename from node_modules/sigstore/dist/types/fetch.js rename to node_modules/@sigstore/verify/dist/shared.types.js diff --git a/node_modules/sigstore/dist/tlog/verify/checkpoint.js b/node_modules/@sigstore/verify/dist/timestamp/checkpoint.js similarity index 59% rename from node_modules/sigstore/dist/tlog/verify/checkpoint.js rename to node_modules/@sigstore/verify/dist/timestamp/checkpoint.js index f6f35a5cad64d..4668c2f45ad76 100644 --- a/node_modules/sigstore/dist/tlog/verify/checkpoint.js +++ b/node_modules/@sigstore/verify/dist/timestamp/checkpoint.js @@ -1,8 +1,24 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.verifyCheckpoint = void 0; -const error_1 = require("../../error"); -const util_1 = require("../../util"); +/* +Copyright 2023 The Sigstore Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +const core_1 = require("@sigstore/core"); +const error_1 = require("../error"); +const trust_1 = require("../trust"); // Separator between the note and the signatures in a checkpoint const CHECKPOINT_SEPARATOR = '\n\n'; // Checkpoint signatures are of the following form: @@ -23,17 +39,44 @@ const SIGNATURE_REGEX = /\u2014 (\S+) (\S+)\n/g; function verifyCheckpoint(entry, tlogs) { // Filter tlog instances to just those which were valid at the time of the // entry - const validTLogs = filterTLogInstances(tlogs, entry.integratedTime); + const validTLogs = (0, trust_1.filterTLogAuthorities)(tlogs, { + targetDate: new Date(Number(entry.integratedTime) * 1000), + }); const inclusionProof = entry.inclusionProof; const signedNote = SignedNote.fromString(inclusionProof.checkpoint.envelope); const checkpoint = LogCheckpoint.fromString(signedNote.note); - // Verify that the signatures in the checkpoint are all valid, also check - // that the root hash from the checkpoint matches the root hash in the + // Verify that the signatures in the checkpoint are all valid + if (!verifySignedNote(signedNote, validTLogs)) { + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROOF_ERROR', + message: 'invalid checkpoint signature', + }); + } + // Verify that the root hash from the checkpoint matches the root hash in the // inclusion proof - return (signedNote.verify(validTLogs) && - util_1.crypto.bufferEqual(checkpoint.logHash, inclusionProof.rootHash)); + if (!core_1.crypto.bufferEqual(checkpoint.logHash, inclusionProof.rootHash)) { + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROOF_ERROR', + message: 'root hash mismatch', + }); + } } exports.verifyCheckpoint = verifyCheckpoint; +// Verifies the signatures in the SignedNote. For each signature, the +// corresponding transparency log is looked up by the key hint and the +// signature is verified against the public key in the transparency log. +// Throws an error if any of the signatures are invalid. +function verifySignedNote(signedNote, tlogs) { + const data = Buffer.from(signedNote.note, 'utf-8'); + return signedNote.signatures.every((signature) => { + // Find the transparency log instance with the matching key hint + const tlog = tlogs.find((tlog) => core_1.crypto.bufferEqual(tlog.logID.subarray(0, 4), signature.keyHint)); + if (!tlog) { + return false; + } + return core_1.crypto.verify(data, tlog.publicKey, signature.signature); + }); +} // SignedNote represents a signed note from a transparency log checkpoint. Consists // of a body (or note) and one more signatures calculated over the body. See // https://github.com/transparency-dev/formats/blob/main/log/README.md#signed-envelope @@ -45,7 +88,10 @@ class SignedNote { // Deserialize a SignedNote from a string static fromString(envelope) { if (!envelope.includes(CHECKPOINT_SEPARATOR)) { - throw new error_1.VerificationError('malformed checkpoint: no separator'); + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROOF_ERROR', + message: 'missing checkpoint separator', + }); } // Split the note into the header and the data portions at the separator const split = envelope.indexOf(CHECKPOINT_SEPARATOR); @@ -60,7 +106,10 @@ class SignedNote { const [, name, signature] = match; const sigBytes = Buffer.from(signature, 'base64'); if (sigBytes.length < 5) { - throw new error_1.VerificationError('malformed checkpoint: invalid signature'); + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROOF_ERROR', + message: 'malformed checkpoint signature', + }); } return { name, @@ -69,26 +118,13 @@ class SignedNote { }; }); if (signatures.length === 0) { - throw new error_1.VerificationError('malformed checkpoint: no signatures'); + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROOF_ERROR', + message: 'no signatures found in checkpoint', + }); } return new SignedNote(header, signatures); } - // Verifies the signatures in the SignedNote. For each signature, the - // corresponding transparency log is looked up by the key hint and the - // signature is verified against the public key in the transparency log. - // Throws an error if any of the signatures are invalid. - verify(tlogs) { - const data = Buffer.from(this.note, 'utf-8'); - return this.signatures.every((signature) => { - // Find the transparency log instance with the matching key hint - const tlog = tlogs.find((tlog) => util_1.crypto.bufferEqual(tlog.logId.keyId.subarray(0, 4), signature.keyHint)); - if (!tlog) { - return false; - } - const publicKey = util_1.crypto.createPublicKey(tlog.publicKey.rawBytes); - return util_1.crypto.verifyBlob(data, publicKey, signature.signature); - }); - } } // LogCheckpoint represents a transparency log checkpoint. Consists of the // following: @@ -108,7 +144,10 @@ class LogCheckpoint { static fromString(note) { const lines = note.trim().split('\n'); if (lines.length < 4) { - throw new error_1.VerificationError('malformed checkpoint: too few lines in header'); + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROOF_ERROR', + message: 'too few lines in checkpoint header', + }); } const origin = lines[0]; const logSize = BigInt(lines[1]); @@ -117,32 +156,3 @@ class LogCheckpoint { return new LogCheckpoint(origin, logSize, rootHash, rest); } } -// Filter the list of tlog instances to only those which have usable public -// keys and were valid at the given time. -function filterTLogInstances(tlogInstances, integratedTime) { - const targetDate = new Date(Number(integratedTime) * 1000); - return tlogInstances.filter((tlog) => { - // Must have a log ID - if (!tlog.logId) { - return false; - } - // If the tlog doesn't have a public key, we can't use it - const publicKey = tlog.publicKey; - if (publicKey === undefined) { - return false; - } - // If the tlog doesn't have a rawBytes field, we can't use it - if (publicKey.rawBytes === undefined) { - return false; - } - // If the tlog doesn't have a validFor field, we don't need to check it - const validFor = publicKey.validFor; - if (validFor === undefined) { - return true; - } - // Check that the integrated time is within the validFor range - return (validFor.start !== undefined && - validFor.start <= targetDate && - (validFor.end === undefined || targetDate <= validFor.end)); - }); -} diff --git a/node_modules/@sigstore/verify/dist/timestamp/index.js b/node_modules/@sigstore/verify/dist/timestamp/index.js new file mode 100644 index 0000000000000..0da554f648d25 --- /dev/null +++ b/node_modules/@sigstore/verify/dist/timestamp/index.js @@ -0,0 +1,47 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyTLogTimestamp = exports.verifyTSATimestamp = void 0; +const error_1 = require("../error"); +const checkpoint_1 = require("./checkpoint"); +const merkle_1 = require("./merkle"); +const set_1 = require("./set"); +const tsa_1 = require("./tsa"); +function verifyTSATimestamp(timestamp, data, timestampAuthorities) { + (0, tsa_1.verifyRFC3161Timestamp)(timestamp, data, timestampAuthorities); + return { + type: 'timestamp-authority', + logID: timestamp.signerSerialNumber, + timestamp: timestamp.signingTime, + }; +} +exports.verifyTSATimestamp = verifyTSATimestamp; +function verifyTLogTimestamp(entry, tlogAuthorities) { + let inclusionVerified = false; + if (isTLogEntryWithInclusionPromise(entry)) { + (0, set_1.verifyTLogSET)(entry, tlogAuthorities); + inclusionVerified = true; + } + if (isTLogEntryWithInclusionProof(entry)) { + (0, merkle_1.verifyMerkleInclusion)(entry); + (0, checkpoint_1.verifyCheckpoint)(entry, tlogAuthorities); + inclusionVerified = true; + } + if (!inclusionVerified) { + throw new error_1.VerificationError({ + code: 'TLOG_MISSING_INCLUSION_ERROR', + message: 'inclusion could not be verified', + }); + } + return { + type: 'transparency-log', + logID: entry.logId.keyId, + timestamp: new Date(Number(entry.integratedTime) * 1000), + }; +} +exports.verifyTLogTimestamp = verifyTLogTimestamp; +function isTLogEntryWithInclusionPromise(entry) { + return entry.inclusionPromise !== undefined; +} +function isTLogEntryWithInclusionProof(entry) { + return entry.inclusionProof !== undefined; +} diff --git a/node_modules/sigstore/dist/tlog/verify/merkle.js b/node_modules/@sigstore/verify/dist/timestamp/merkle.js similarity index 76% rename from node_modules/sigstore/dist/tlog/verify/merkle.js rename to node_modules/@sigstore/verify/dist/timestamp/merkle.js index 0f246af4a28a3..9895d01b7abc0 100644 --- a/node_modules/sigstore/dist/tlog/verify/merkle.js +++ b/node_modules/@sigstore/verify/dist/timestamp/merkle.js @@ -1,7 +1,4 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; Object.defineProperty(exports, "__esModule", { value: true }); exports.verifyMerkleInclusion = void 0; /* @@ -19,8 +16,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -const crypto_1 = __importDefault(require("crypto")); -const error_1 = require("../../error"); +const core_1 = require("@sigstore/core"); +const error_1 = require("../error"); const RFC6962_LEAF_HASH_PREFIX = Buffer.from([0x00]); const RFC6962_NODE_HASH_PREFIX = Buffer.from([0x01]); function verifyMerkleInclusion(entry) { @@ -28,13 +25,19 @@ function verifyMerkleInclusion(entry) { const logIndex = BigInt(inclusionProof.logIndex); const treeSize = BigInt(inclusionProof.treeSize); if (logIndex < 0n || logIndex >= treeSize) { - throw new error_1.VerificationError('invalid inclusion proof index'); + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROOF_ERROR', + message: `invalid index: ${logIndex}`, + }); } // Figure out which subset of hashes corresponds to the inner and border // nodes const { inner, border } = decompInclProof(logIndex, treeSize); if (inclusionProof.hashes.length !== inner + border) { - throw new error_1.VerificationError('invalid inclusion proof length'); + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROOF_ERROR', + message: 'invalid hash count', + }); } const innerHashes = inclusionProof.hashes.slice(0, inner); const borderHashes = inclusionProof.hashes.slice(inner); @@ -43,7 +46,12 @@ function verifyMerkleInclusion(entry) { // Chain the hashes belonging to the inner and border portions const calculatedHash = chainBorderRight(chainInner(leafHash, innerHashes, logIndex), borderHashes); // Calculated hash should match the root hash in the inclusion proof - return bufferEqual(calculatedHash, inclusionProof.rootHash); + if (!core_1.crypto.bufferEqual(calculatedHash, inclusionProof.rootHash)) { + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROOF_ERROR', + message: 'calculated root hash does not match inclusion proof', + }); + } } exports.verifyMerkleInclusion = verifyMerkleInclusion; // Breaks down inclusion proof for a leaf at the specified index in a tree of @@ -77,8 +85,8 @@ function innerProofSize(index, size) { } // Counts the number of ones in the binary representation of the given number. // https://en.wikipedia.org/wiki/Hamming_weight -function onesCount(x) { - return x.toString(2).split('1').length - 1; +function onesCount(num) { + return num.toString(2).split('1').length - 1; } // Returns the number of bits necessary to represent an integer in binary. function bitLength(n) { @@ -90,24 +98,8 @@ function bitLength(n) { // Hashing logic according to RFC6962. // https://datatracker.ietf.org/doc/html/rfc6962#section-2 function hashChildren(left, right) { - const hasher = crypto_1.default.createHash('sha256'); - hasher.update(RFC6962_NODE_HASH_PREFIX); - hasher.update(left); - hasher.update(right); - return hasher.digest(); + return core_1.crypto.hash(RFC6962_NODE_HASH_PREFIX, left, right); } function hashLeaf(leaf) { - const hasher = crypto_1.default.createHash('sha256'); - hasher.update(RFC6962_LEAF_HASH_PREFIX); - hasher.update(leaf); - return hasher.digest(); -} -function bufferEqual(a, b) { - try { - return crypto_1.default.timingSafeEqual(a, b); - } - catch { - /* istanbul ignore next */ - return false; - } + return core_1.crypto.hash(RFC6962_LEAF_HASH_PREFIX, leaf); } diff --git a/node_modules/@sigstore/verify/dist/timestamp/set.js b/node_modules/@sigstore/verify/dist/timestamp/set.js new file mode 100644 index 0000000000000..a6357c06999cb --- /dev/null +++ b/node_modules/@sigstore/verify/dist/timestamp/set.js @@ -0,0 +1,61 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyTLogSET = void 0; +/* +Copyright 2023 The Sigstore Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +const core_1 = require("@sigstore/core"); +const error_1 = require("../error"); +const trust_1 = require("../trust"); +// Verifies the SET for the given entry against the list of trusted +// transparency logs. Returns true if the SET can be verified against at least +// one of the trusted logs; otherwise, returns false. +function verifyTLogSET(entry, tlogs) { + // Filter the list of tlog instances to only those which might be able to + // verify the SET + const validTLogs = (0, trust_1.filterTLogAuthorities)(tlogs, { + logID: entry.logId.keyId, + targetDate: new Date(Number(entry.integratedTime) * 1000), + }); + // Check to see if we can verify the SET against any of the valid tlogs + const verified = validTLogs.some((tlog) => { + // Re-create the original Rekor verification payload + const payload = toVerificationPayload(entry); + // Canonicalize the payload and turn into a buffer for verification + const data = Buffer.from(core_1.json.canonicalize(payload), 'utf8'); + // Extract the SET from the tlog entry + const signature = entry.inclusionPromise.signedEntryTimestamp; + return core_1.crypto.verify(data, tlog.publicKey, signature); + }); + if (!verified) { + throw new error_1.VerificationError({ + code: 'TLOG_INCLUSION_PROMISE_ERROR', + message: 'inclusion promise could not be verified', + }); + } +} +exports.verifyTLogSET = verifyTLogSET; +// Returns a properly formatted "VerificationPayload" for one of the +// transaction log entires in the given bundle which can be used for SET +// verification. +function toVerificationPayload(entry) { + const { integratedTime, logIndex, logId, canonicalizedBody } = entry; + return { + body: canonicalizedBody.toString('base64'), + integratedTime: Number(integratedTime), + logIndex: Number(logIndex), + logID: logId.keyId.toString('hex'), + }; +} diff --git a/node_modules/@sigstore/verify/dist/timestamp/tsa.js b/node_modules/@sigstore/verify/dist/timestamp/tsa.js new file mode 100644 index 0000000000000..7b095bc3a7f90 --- /dev/null +++ b/node_modules/@sigstore/verify/dist/timestamp/tsa.js @@ -0,0 +1,74 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyRFC3161Timestamp = void 0; +const core_1 = require("@sigstore/core"); +const error_1 = require("../error"); +const certificate_1 = require("../key/certificate"); +const trust_1 = require("../trust"); +function verifyRFC3161Timestamp(timestamp, data, timestampAuthorities) { + const signingTime = timestamp.signingTime; + // Filter for CAs which were valid at the time of signing + timestampAuthorities = (0, trust_1.filterCertAuthorities)(timestampAuthorities, { + start: signingTime, + end: signingTime, + }); + // Filter for CAs which match serial and issuer embedded in the timestamp + timestampAuthorities = filterCAsBySerialAndIssuer(timestampAuthorities, { + serialNumber: timestamp.signerSerialNumber, + issuer: timestamp.signerIssuer, + }); + // Check that we can verify the timestamp with AT LEAST ONE of the remaining + // CAs + const verified = timestampAuthorities.some((ca) => { + try { + verifyTimestampForCA(timestamp, data, ca); + return true; + } + catch (e) { + return false; + } + }); + if (!verified) { + throw new error_1.VerificationError({ + code: 'TIMESTAMP_ERROR', + message: 'timestamp could not be verified', + }); + } +} +exports.verifyRFC3161Timestamp = verifyRFC3161Timestamp; +function verifyTimestampForCA(timestamp, data, ca) { + const [leaf, ...cas] = ca.certChain; + const signingKey = core_1.crypto.createPublicKey(leaf.publicKey); + const signingTime = timestamp.signingTime; + // Verify the certificate chain for the provided CA + try { + new certificate_1.CertificateChainVerifier({ + untrustedCert: leaf, + trustedCerts: cas, + }).verify(); + } + catch (e) { + throw new error_1.VerificationError({ + code: 'TIMESTAMP_ERROR', + message: 'invalid certificate chain', + }); + } + // Check that all of the CA certs were valid at the time of signing + const validAtSigningTime = ca.certChain.every((cert) => cert.validForDate(signingTime)); + if (!validAtSigningTime) { + throw new error_1.VerificationError({ + code: 'TIMESTAMP_ERROR', + message: 'timestamp was signed with an expired certificate', + }); + } + // Check that the signing certificate's key can be used to verify the + // timestamp signature. + timestamp.verify(data, signingKey); +} +// Filters the list of CAs to those which have a leaf signing certificate which +// matches the given serial number and issuer. +function filterCAsBySerialAndIssuer(timestampAuthorities, criteria) { + return timestampAuthorities.filter((ca) => ca.certChain.length > 0 && + core_1.crypto.bufferEqual(ca.certChain[0].serialNumber, criteria.serialNumber) && + core_1.crypto.bufferEqual(ca.certChain[0].issuer, criteria.issuer)); +} diff --git a/node_modules/@sigstore/verify/dist/tlog/dsse.js b/node_modules/@sigstore/verify/dist/tlog/dsse.js new file mode 100644 index 0000000000000..bf430e61dde56 --- /dev/null +++ b/node_modules/@sigstore/verify/dist/tlog/dsse.js @@ -0,0 +1,58 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyDSSETLogBody = void 0; +/* +Copyright 2023 The Sigstore Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +const error_1 = require("../error"); +// Compare the given intoto tlog entry to the given bundle +function verifyDSSETLogBody(tlogEntry, content) { + switch (tlogEntry.apiVersion) { + case '0.0.1': + return verifyDSSE001TLogBody(tlogEntry, content); + default: + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: `unsupported dsse version: ${tlogEntry.apiVersion}`, + }); + } +} +exports.verifyDSSETLogBody = verifyDSSETLogBody; +// Compare the given dsse v0.0.1 tlog entry to the given DSSE envelope. +function verifyDSSE001TLogBody(tlogEntry, content) { + // Ensure the bundle's DSSE only contains a single signature + if (tlogEntry.spec.signatures?.length !== 1) { + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: 'signature count mismatch', + }); + } + const tlogSig = tlogEntry.spec.signatures[0].signature; + // Ensure that the signature in the bundle's DSSE matches tlog entry + if (!content.compareSignature(Buffer.from(tlogSig, 'base64'))) + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: 'tlog entry signature mismatch', + }); + // Ensure the digest of the bundle's DSSE payload matches the digest in the + // tlog entry + const tlogHash = tlogEntry.spec.payloadHash?.value || ''; + if (!content.compareDigest(Buffer.from(tlogHash, 'hex'))) { + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: 'DSSE payload hash mismatch', + }); + } +} diff --git a/node_modules/@sigstore/verify/dist/tlog/hashedrekord.js b/node_modules/@sigstore/verify/dist/tlog/hashedrekord.js new file mode 100644 index 0000000000000..d1758858f030d --- /dev/null +++ b/node_modules/@sigstore/verify/dist/tlog/hashedrekord.js @@ -0,0 +1,52 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyHashedRekordTLogBody = void 0; +/* +Copyright 2023 The Sigstore Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +const error_1 = require("../error"); +// Compare the given hashedrekord tlog entry to the given bundle +function verifyHashedRekordTLogBody(tlogEntry, content) { + switch (tlogEntry.apiVersion) { + case '0.0.1': + return verifyHashedrekord001TLogBody(tlogEntry, content); + default: + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: `unsupported hashedrekord version: ${tlogEntry.apiVersion}`, + }); + } +} +exports.verifyHashedRekordTLogBody = verifyHashedRekordTLogBody; +// Compare the given hashedrekord v0.0.1 tlog entry to the given message +// signature +function verifyHashedrekord001TLogBody(tlogEntry, content) { + // Ensure that the bundles message signature matches the tlog entry + const tlogSig = tlogEntry.spec.signature.content || ''; + if (!content.compareSignature(Buffer.from(tlogSig, 'base64'))) { + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: 'signature mismatch', + }); + } + // Ensure that the bundle's message digest matches the tlog entry + const tlogDigest = tlogEntry.spec.data.hash?.value || ''; + if (!content.compareDigest(Buffer.from(tlogDigest, 'hex'))) { + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: 'digest mismatch', + }); + } +} diff --git a/node_modules/@sigstore/verify/dist/tlog/index.js b/node_modules/@sigstore/verify/dist/tlog/index.js new file mode 100644 index 0000000000000..adfc70ed51ad0 --- /dev/null +++ b/node_modules/@sigstore/verify/dist/tlog/index.js @@ -0,0 +1,48 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyTLogBody = void 0; +/* +Copyright 2023 The Sigstore Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +const error_1 = require("../error"); +const dsse_1 = require("./dsse"); +const hashedrekord_1 = require("./hashedrekord"); +const intoto_1 = require("./intoto"); +// Verifies that the given tlog entry matches the supplied signature content. +function verifyTLogBody(entry, sigContent) { + const { kind, version } = entry.kindVersion; + const body = JSON.parse(entry.canonicalizedBody.toString('utf8')); + if (kind !== body.kind || version !== body.apiVersion) { + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: `kind/version mismatch - expected: ${kind}/${version}, received: ${body.kind}/${body.apiVersion}`, + }); + } + switch (body.kind) { + case 'dsse': + return (0, dsse_1.verifyDSSETLogBody)(body, sigContent); + case 'intoto': + return (0, intoto_1.verifyIntotoTLogBody)(body, sigContent); + case 'hashedrekord': + return (0, hashedrekord_1.verifyHashedRekordTLogBody)(body, sigContent); + /* istanbul ignore next */ + default: + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: `unsupported kind: ${kind}`, + }); + } +} +exports.verifyTLogBody = verifyTLogBody; diff --git a/node_modules/@sigstore/verify/dist/tlog/intoto.js b/node_modules/@sigstore/verify/dist/tlog/intoto.js new file mode 100644 index 0000000000000..e706887a95043 --- /dev/null +++ b/node_modules/@sigstore/verify/dist/tlog/intoto.js @@ -0,0 +1,62 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.verifyIntotoTLogBody = void 0; +/* +Copyright 2023 The Sigstore Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +const error_1 = require("../error"); +// Compare the given intoto tlog entry to the given bundle +function verifyIntotoTLogBody(tlogEntry, content) { + switch (tlogEntry.apiVersion) { + case '0.0.2': + return verifyIntoto002TLogBody(tlogEntry, content); + default: + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: `unsupported intoto version: ${tlogEntry.apiVersion}`, + }); + } +} +exports.verifyIntotoTLogBody = verifyIntotoTLogBody; +// Compare the given intoto v0.0.2 tlog entry to the given DSSE envelope. +function verifyIntoto002TLogBody(tlogEntry, content) { + // Ensure the bundle's DSSE contains a single signature + if (tlogEntry.spec.content.envelope.signatures?.length !== 1) { + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: 'signature count mismatch', + }); + } + // Signature is double-base64-encoded in the tlog entry + const tlogSig = base64Decode(tlogEntry.spec.content.envelope.signatures[0].sig); + // Ensure that the signature in the bundle's DSSE matches tlog entry + if (!content.compareSignature(Buffer.from(tlogSig, 'base64'))) + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: 'tlog entry signature mismatch', + }); + // Ensure the digest of the bundle's DSSE payload matches the digest in the + // tlog entry + const tlogHash = tlogEntry.spec.content.payloadHash?.value || ''; + if (!content.compareDigest(Buffer.from(tlogHash, 'hex'))) { + throw new error_1.VerificationError({ + code: 'TLOG_BODY_ERROR', + message: 'DSSE payload hash mismatch', + }); + } +} +function base64Decode(str) { + return Buffer.from(str, 'base64').toString('utf-8'); +} diff --git a/node_modules/@sigstore/verify/dist/trust/filter.js b/node_modules/@sigstore/verify/dist/trust/filter.js new file mode 100644 index 0000000000000..c09d055913c4c --- /dev/null +++ b/node_modules/@sigstore/verify/dist/trust/filter.js @@ -0,0 +1,24 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.filterTLogAuthorities = exports.filterCertAuthorities = void 0; +function filterCertAuthorities(certAuthorities, criteria) { + return certAuthorities.filter((ca) => { + return (ca.validFor.start <= criteria.start && ca.validFor.end >= criteria.end); + }); +} +exports.filterCertAuthorities = filterCertAuthorities; +// Filter the list of tlog instances to only those which match the given log +// ID and have public keys which are valid for the given integrated time. +function filterTLogAuthorities(tlogAuthorities, criteria) { + return tlogAuthorities.filter((tlog) => { + // If we're filtering by log ID and the log IDs don't match, we can't use + // this tlog + if (criteria.logID && !tlog.logID.equals(criteria.logID)) { + return false; + } + // Check that the integrated time is within the validFor range + return (tlog.validFor.start <= criteria.targetDate && + criteria.targetDate <= tlog.validFor.end); + }); +} +exports.filterTLogAuthorities = filterTLogAuthorities; diff --git a/node_modules/@sigstore/verify/dist/trust/index.js b/node_modules/@sigstore/verify/dist/trust/index.js new file mode 100644 index 0000000000000..7991f351949a0 --- /dev/null +++ b/node_modules/@sigstore/verify/dist/trust/index.js @@ -0,0 +1,75 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.toTrustMaterial = exports.filterTLogAuthorities = exports.filterCertAuthorities = void 0; +/* +Copyright 2023 The Sigstore Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +const core_1 = require("@sigstore/core"); +const error_1 = require("../error"); +const BEGINNING_OF_TIME = new Date(0); +const END_OF_TIME = new Date(8640000000000000); +var filter_1 = require("./filter"); +Object.defineProperty(exports, "filterCertAuthorities", { enumerable: true, get: function () { return filter_1.filterCertAuthorities; } }); +Object.defineProperty(exports, "filterTLogAuthorities", { enumerable: true, get: function () { return filter_1.filterTLogAuthorities; } }); +function toTrustMaterial(root, keys) { + const keyFinder = typeof keys === 'function' ? keys : keyLocator(keys); + return { + certificateAuthorities: root.certificateAuthorities.map(createCertAuthority), + timestampAuthorities: root.timestampAuthorities.map(createCertAuthority), + tlogs: root.tlogs.map(createTLogAuthority), + ctlogs: root.ctlogs.map(createTLogAuthority), + publicKey: keyFinder, + }; +} +exports.toTrustMaterial = toTrustMaterial; +function createTLogAuthority(tlogInstance) { + return { + logID: tlogInstance.logId.keyId, + publicKey: core_1.crypto.createPublicKey(tlogInstance.publicKey.rawBytes), + validFor: { + start: tlogInstance.publicKey.validFor?.start || BEGINNING_OF_TIME, + end: tlogInstance.publicKey.validFor?.end || END_OF_TIME, + }, + }; +} +function createCertAuthority(ca) { + return { + certChain: ca.certChain.certificates.map((cert) => { + return core_1.X509Certificate.parse(cert.rawBytes); + }), + validFor: { + start: ca.validFor?.start || BEGINNING_OF_TIME, + end: ca.validFor?.end || END_OF_TIME, + }, + }; +} +function keyLocator(keys) { + return (hint) => { + const key = (keys || {})[hint]; + if (!key) { + throw new error_1.VerificationError({ + code: 'PUBLIC_KEY_ERROR', + message: `key not found: ${hint}`, + }); + } + return { + publicKey: core_1.crypto.createPublicKey(key.rawBytes), + validFor: (date) => { + return ((key.validFor?.start || BEGINNING_OF_TIME) <= date && + (key.validFor?.end || END_OF_TIME) >= date); + }, + }; + }; +} diff --git a/node_modules/@sigstore/verify/dist/trust/trust.types.js b/node_modules/@sigstore/verify/dist/trust/trust.types.js new file mode 100644 index 0000000000000..c8ad2e549bdc6 --- /dev/null +++ b/node_modules/@sigstore/verify/dist/trust/trust.types.js @@ -0,0 +1,2 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/node_modules/@sigstore/verify/dist/verifier.js b/node_modules/@sigstore/verify/dist/verifier.js new file mode 100644 index 0000000000000..829727cd1d40a --- /dev/null +++ b/node_modules/@sigstore/verify/dist/verifier.js @@ -0,0 +1,141 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Verifier = void 0; +/* +Copyright 2023 The Sigstore Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +const util_1 = require("util"); +const error_1 = require("./error"); +const key_1 = require("./key"); +const policy_1 = require("./policy"); +const timestamp_1 = require("./timestamp"); +const tlog_1 = require("./tlog"); +class Verifier { + constructor(trustMaterial, options = {}) { + this.trustMaterial = trustMaterial; + this.options = { + ctlogThreshold: options.ctlogThreshold ?? 1, + tlogThreshold: options.tlogThreshold ?? 1, + tsaThreshold: options.tsaThreshold ?? 0, + }; + } + verify(entity, policy) { + const timestamps = this.verifyTimestamps(entity); + const signer = this.verifySigningKey(entity, timestamps); + this.verifyTLogs(entity); + this.verifySignature(entity, signer); + if (policy) { + this.verifyPolicy(policy, signer.identity || {}); + } + return signer; + } + // Checks that all of the timestamps in the entity are valid and returns them + verifyTimestamps(entity) { + let tlogCount = 0; + let tsaCount = 0; + const timestamps = entity.timestamps.map((timestamp) => { + switch (timestamp.$case) { + case 'timestamp-authority': + tsaCount++; + return (0, timestamp_1.verifyTSATimestamp)(timestamp.timestamp, entity.signature.signature, this.trustMaterial.timestampAuthorities); + case 'transparency-log': + tlogCount++; + return (0, timestamp_1.verifyTLogTimestamp)(timestamp.tlogEntry, this.trustMaterial.tlogs); + } + }); + // Check for duplicate timestamps + if (containsDupes(timestamps)) { + throw new error_1.VerificationError({ + code: 'TIMESTAMP_ERROR', + message: 'duplicate timestamp', + }); + } + if (tlogCount < this.options.tlogThreshold) { + throw new error_1.VerificationError({ + code: 'TIMESTAMP_ERROR', + message: `expected ${this.options.tlogThreshold} tlog timestamps, got ${tlogCount}`, + }); + } + if (tsaCount < this.options.tsaThreshold) { + throw new error_1.VerificationError({ + code: 'TIMESTAMP_ERROR', + message: `expected ${this.options.tsaThreshold} tsa timestamps, got ${tsaCount}`, + }); + } + return timestamps.map((t) => t.timestamp); + } + // Checks that the signing key is valid for all of the the supplied timestamps + // and returns the signer. + verifySigningKey({ key }, timestamps) { + switch (key.$case) { + case 'public-key': { + return (0, key_1.verifyPublicKey)(key.hint, timestamps, this.trustMaterial); + } + case 'certificate': { + const result = (0, key_1.verifyCertificate)(key.certificate, timestamps, this.trustMaterial); + /* istanbul ignore next - no fixture */ + if (containsDupes(result.scts)) { + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: 'duplicate SCT', + }); + } + if (result.scts.length < this.options.ctlogThreshold) { + throw new error_1.VerificationError({ + code: 'CERTIFICATE_ERROR', + message: `expected ${this.options.ctlogThreshold} SCTs, got ${result.scts.length}`, + }); + } + return result.signer; + } + } + } + // Checks that the tlog entries are valid for the supplied content + verifyTLogs({ signature: content, tlogEntries }) { + tlogEntries.forEach((entry) => (0, tlog_1.verifyTLogBody)(entry, content)); + } + // Checks that the signature is valid for the supplied content + verifySignature(entity, signer) { + if (!entity.signature.verifySignature(signer.key)) { + throw new error_1.VerificationError({ + code: 'SIGNATURE_ERROR', + message: 'signature verification failed', + }); + } + } + verifyPolicy(policy, identity) { + // Check the subject alternative name of the signer matches the policy + if (policy.subjectAlternativeName) { + (0, policy_1.verifySubjectAlternativeName)(policy.subjectAlternativeName, identity.subjectAlternativeName); + } + // Check that the extensions of the signer match the policy + if (policy.extensions) { + (0, policy_1.verifyExtensions)(policy.extensions, identity.extensions); + } + } +} +exports.Verifier = Verifier; +// Checks for duplicate items in the array. Objects are compared using +// deep equality. +function containsDupes(arr) { + for (let i = 0; i < arr.length; i++) { + for (let j = i + 1; j < arr.length; j++) { + if ((0, util_1.isDeepStrictEqual)(arr[i], arr[j])) { + return true; + } + } + } + return false; +} diff --git a/node_modules/@sigstore/verify/package.json b/node_modules/@sigstore/verify/package.json new file mode 100644 index 0000000000000..74cd532ecf0bb --- /dev/null +++ b/node_modules/@sigstore/verify/package.json @@ -0,0 +1,36 @@ +{ + "name": "@sigstore/verify", + "version": "0.1.0", + "description": "Verification of Sigstore signatures", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "clean": "shx rm -rf dist *.tsbuildinfo", + "build": "tsc --build", + "test": "jest" + }, + "files": [ + "dist" + ], + "author": "bdehamer@github.com", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "git+https://github.com/sigstore/sigstore-js.git" + }, + "bugs": { + "url": "https://github.com/sigstore/sigstore-js/issues" + }, + "homepage": "https://github.com/sigstore/sigstore-js/tree/main/packages/verify#readme", + "publishConfig": { + "provenance": true + }, + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.1", + "@sigstore/bundle": "^2.1.1", + "@sigstore/core": "^0.2.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } +} diff --git a/node_modules/sigstore/dist/ca/verify/chain.js b/node_modules/sigstore/dist/ca/verify/chain.js deleted file mode 100644 index 3246c7a154e2d..0000000000000 --- a/node_modules/sigstore/dist/ca/verify/chain.js +++ /dev/null @@ -1,63 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.verifyChain = void 0; -/* -Copyright 2022 The Sigstore Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -const error_1 = require("../../error"); -const cert_1 = require("../../x509/cert"); -const verify_1 = require("../../x509/verify"); -function verifyChain(certificate, certificateAuthorities) { - const untrustedCert = cert_1.x509Certificate.parse(certificate.rawBytes); - // Filter the list of certificate authorities to those which are valid for the - // signing certificate's notBefore date. - const validCAs = filterCertificateAuthorities(certificateAuthorities, untrustedCert.notBefore); - if (validCAs.length === 0) { - throw new error_1.VerificationError('No valid certificate authorities'); - } - let trustedChain = []; - // Loop through all valid CAs and attempt to verify the certificate chain - const verified = validCAs.find((ca) => { - const trustedCerts = parseCerts(ca.certChain?.certificates || []); - try { - trustedChain = (0, verify_1.verifyCertificateChain)({ - untrustedCert, - trustedCerts, - validAt: untrustedCert.notBefore, - }); - return true; - } - catch (e) { - return false; - } - }); - if (!verified) { - throw new error_1.VerificationError('No valid certificate chain'); - } - return trustedChain; -} -exports.verifyChain = verifyChain; -// Filter the list of certificate authorities to those which are valid for the -// given date. -function filterCertificateAuthorities(certificateAuthorities, validAt) { - return certificateAuthorities.filter((ca) => ca.validFor && - ca.validFor.start && - ca.validFor.start <= validAt && - (!ca.validFor.end || validAt <= ca.validFor.end)); -} -// Parse the raw bytes of a certificate into an x509Certificate object. -function parseCerts(certs) { - return certs.map((cert) => cert_1.x509Certificate.parse(cert.rawBytes)); -} diff --git a/node_modules/sigstore/dist/ca/verify/index.js b/node_modules/sigstore/dist/ca/verify/index.js deleted file mode 100644 index 32f85c828fe5a..0000000000000 --- a/node_modules/sigstore/dist/ca/verify/index.js +++ /dev/null @@ -1,22 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.verifySigningCertificate = void 0; -const chain_1 = require("./chain"); -const sct_1 = require("./sct"); -const signer_1 = require("./signer"); -function verifySigningCertificate(bundle, trustedRoot, options) { - // Check that a trusted certificate chain can be found for the signing - // certificate in the bundle. Only the first certificate in the bundle's - // chain is used -- everything else must come from the trusted root. - const trustedChain = (0, chain_1.verifyChain)(bundle.verificationMaterial.content.x509CertificateChain.certificates[0], trustedRoot.certificateAuthorities); - // Unless disabled, verify the SCTs in the signing certificate - if (options.ctlogOptions.disable === false) { - (0, sct_1.verifySCTs)(trustedChain, trustedRoot.ctlogs, options.ctlogOptions); - } - // Verify the signing certificate against the provided identities - // if provided - if (options.signers) { - (0, signer_1.verifySignerIdentity)(trustedChain[0], options.signers.certificateIdentities); - } -} -exports.verifySigningCertificate = verifySigningCertificate; diff --git a/node_modules/sigstore/dist/ca/verify/sct.js b/node_modules/sigstore/dist/ca/verify/sct.js deleted file mode 100644 index 771c6dd4c0a7f..0000000000000 --- a/node_modules/sigstore/dist/ca/verify/sct.js +++ /dev/null @@ -1,30 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.verifySCTs = void 0; -/* -Copyright 2022 The Sigstore Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -const error_1 = require("../../error"); -function verifySCTs(certificateChain, ctLogs, options) { - const signingCert = certificateChain[0]; - const issuerCert = certificateChain[1]; - const sctResults = signingCert.verifySCTs(issuerCert, ctLogs); - // Count the number of verified SCTs which were found - const verifiedSCTCount = sctResults.filter((sct) => sct.verified).length; - if (verifiedSCTCount < options.threshold) { - throw new error_1.VerificationError(`Not enough SCTs verified (found ${verifiedSCTCount}, need ${options.threshold})`); - } -} -exports.verifySCTs = verifySCTs; diff --git a/node_modules/sigstore/dist/ca/verify/signer.js b/node_modules/sigstore/dist/ca/verify/signer.js deleted file mode 100644 index 6f47651b944c9..0000000000000 --- a/node_modules/sigstore/dist/ca/verify/signer.js +++ /dev/null @@ -1,146 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.verifySignerIdentity = void 0; -/* -Copyright 2023 The Sigstore Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -const error_1 = require("../../error"); -const sigstore = __importStar(require("../../types/sigstore")); -// https://github.com/sigstore/fulcio/blob/main/docs/oid-info.md#1361415726411--issuer -const OID_FULCIO_ISSUER = '1.3.6.1.4.1.57264.1.1'; -// https://github.com/sigstore/fulcio/blob/main/docs/oid-info.md#1361415726417--othername-san -const OID_FULCIO_USERNAME_SUBJECT = '1.3.6.1.4.1.57264.1.7'; -// Verifies the identity embedded in a Fulcio-issued signing certificate against -// the list of trusted identities. Returns without error if at least one of the -// identities matches the signing certificate; otherwise, throws a -// VerificationError. -function verifySignerIdentity(signingCert, identities) { - // Check that the signing certificate was issued to at least one of the - // specified identities - const signerVerified = identities.identities.some((identity) => verifyIdentity(signingCert, identity)); - if (!signerVerified) { - throw new error_1.PolicyError({ - code: 'UNTRUSTED_SIGNER_ERROR', - message: 'Certificate issued to untrusted signer', - }); - } -} -exports.verifySignerIdentity = verifySignerIdentity; -// Checks that the specified certificate was issued to the specified identity. -// The certificate must match the issuer, subject alternative name, and an -// optional list of certificate extensions. Returns true if the certificate was -// issued to the identity; otherwise, returns false. -function verifyIdentity(cert, identity) { - return (verifyIssuer(cert, identity.issuer) && - verifySAN(cert, identity.san) && - verifyOIDs(cert, identity.oids)); -} -// Checks the Fulcio issuer extension against the expected issuer. Returns true -// if the issuer matches; otherwise, returns false. -function verifyIssuer(cert, issuer) { - const issuerExtension = cert.extension(OID_FULCIO_ISSUER); - return issuerExtension?.value.toString('ascii') === issuer; -} -// Checks the certificate against the expected subject alternative name. Returns -// true if the SAN matches; otherwise, returns false. -function verifySAN(cert, expectedSAN) { - // Fail if the SAN is not specified or is not a supported type - if (expectedSAN === undefined || - expectedSAN.identity === undefined || - expectedSAN.type === - sigstore.SubjectAlternativeNameType - .SUBJECT_ALTERNATIVE_NAME_TYPE_UNSPECIFIED) { - return false; - } - const sanExtension = cert.extSubjectAltName; - // Fail if the certificate does not have a SAN extension - if (!sanExtension) { - return false; - } - let sanValue; - switch (expectedSAN.type) { - case sigstore.SubjectAlternativeNameType.EMAIL: - sanValue = sanExtension.rfc822Name; - break; - case sigstore.SubjectAlternativeNameType.URI: - sanValue = sanExtension.uri; - break; - case sigstore.SubjectAlternativeNameType.OTHER_NAME: - sanValue = sanExtension.otherName(OID_FULCIO_USERNAME_SUBJECT); - break; - } - // Missing SAN value is an automatic failure - if (sanValue === undefined) { - return false; - } - let match; - switch (expectedSAN.identity.$case) { - case 'value': - match = expectedSAN.identity.value; - break; - case 'regexp': - // TODO support regex - break; - } - return sanValue === match; -} -// Checks that the certificate contains the specified extensions. Returns true -// if all extensions are present and match the expected values; otherwise, -// returns false. -function verifyOIDs(cert, oids) { - return oids.every((expectedExtension) => { - if (!expectedExtension.oid) { - return false; - } - const oid = expectedExtension.oid.id.join('.'); - const extension = cert.extension(oid); - // If the extension is not present, or there is no value, return false - const valueObj = extension?.valueObj; - if (!valueObj) { - return false; - } - // Check to see if this is a newer style extension with an embedded - // UTF8String, or an older style extension with a raw string - if (valueObj.subs.length > 0) { - return valueObj.subs[0].value.equals(expectedExtension.value); - } - else { - return valueObj.value.equals(expectedExtension.value); - } - }); -} diff --git a/node_modules/sigstore/dist/config.js b/node_modules/sigstore/dist/config.js index 43c236f0eebd0..b4f0eea74fa4b 100644 --- a/node_modules/sigstore/dist/config.js +++ b/node_modules/sigstore/dist/config.js @@ -1,29 +1,6 @@ "use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; Object.defineProperty(exports, "__esModule", { value: true }); -exports.artifactVerificationOptions = exports.createBundleBuilder = exports.DEFAULT_TIMEOUT = exports.DEFAULT_RETRY = void 0; +exports.createVerificationPolicy = exports.createKeyFinder = exports.createBundleBuilder = exports.DEFAULT_TIMEOUT = exports.DEFAULT_RETRY = void 0; /* Copyright 2023 The Sigstore Authors. @@ -39,8 +16,9 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ +const core_1 = require("@sigstore/core"); const sign_1 = require("@sigstore/sign"); -const sigstore = __importStar(require("./types/sigstore")); +const verify_1 = require("@sigstore/verify"); exports.DEFAULT_RETRY = { retries: 2 }; exports.DEFAULT_TIMEOUT = 5000; function createBundleBuilder(bundleType, options) { @@ -56,6 +34,36 @@ function createBundleBuilder(bundleType, options) { } } exports.createBundleBuilder = createBundleBuilder; +// Translates the public KeySelector type into the KeyFinderFunc type needed by +// the verifier. +function createKeyFinder(keySelector) { + return (hint) => { + const key = keySelector(hint); + if (!key) { + throw new verify_1.VerificationError({ + code: 'PUBLIC_KEY_ERROR', + message: `key not found: ${hint}`, + }); + } + return { + publicKey: core_1.crypto.createPublicKey(key), + validFor: () => true, + }; + }; +} +exports.createKeyFinder = createKeyFinder; +function createVerificationPolicy(options) { + const policy = {}; + const san = options.certificateIdentityEmail || options.certificateIdentityURI; + if (san) { + policy.subjectAlternativeName = san; + } + if (options.certificateIssuer) { + policy.extensions = { issuer: options.certificateIssuer }; + } + return policy; +} +exports.createVerificationPolicy = createVerificationPolicy; // Instantiate the FulcioSigner based on the supplied options. function initSigner(options) { return new sign_1.FulcioSigner({ @@ -71,6 +79,7 @@ function initSigner(options) { function initIdentityProvider(options) { const token = options.identityToken; if (token) { + /* istanbul ignore next */ return { getToken: () => Promise.resolve(token) }; } else { @@ -105,61 +114,3 @@ function isRekorEnabled(options) { function isTSAEnabled(options) { return options.tsaServerURL !== undefined; } -// Assembles the AtifactVerificationOptions from the supplied VerifyOptions. -function artifactVerificationOptions(options) { - // The trusted signers are only used if the options contain a certificate - // issuer - let signers; - if (options.certificateIssuer) { - let san = undefined; - if (options.certificateIdentityEmail) { - san = { - type: sigstore.SubjectAlternativeNameType.EMAIL, - identity: { - $case: 'value', - value: options.certificateIdentityEmail, - }, - }; - } - else if (options.certificateIdentityURI) { - san = { - type: sigstore.SubjectAlternativeNameType.URI, - identity: { - $case: 'value', - value: options.certificateIdentityURI, - }, - }; - } - const oids = Object.entries(options.certificateOIDs || /* istanbul ignore next */ {}).map(([oid, value]) => ({ - oid: { id: oid.split('.').map((s) => parseInt(s, 10)) }, - value: Buffer.from(value), - })); - signers = { - $case: 'certificateIdentities', - certificateIdentities: { - identities: [ - { - issuer: options.certificateIssuer, - san: san, - oids: oids, - }, - ], - }, - }; - } - // Construct the artifact verification options w/ defaults - return { - ctlogOptions: { - disable: options.ctLogThreshold === 0, - threshold: options.ctLogThreshold ?? 1, - detachedSct: false, - }, - tlogOptions: { - disable: options.tlogThreshold === 0, - threshold: options.tlogThreshold ?? 1, - performOnlineVerification: false, - }, - signers, - }; -} -exports.artifactVerificationOptions = artifactVerificationOptions; diff --git a/node_modules/sigstore/dist/index.js b/node_modules/sigstore/dist/index.js index 341c1fa504d1e..7f6a5cf86bbfc 100644 --- a/node_modules/sigstore/dist/index.js +++ b/node_modules/sigstore/dist/index.js @@ -24,9 +24,9 @@ Object.defineProperty(exports, "DEFAULT_REKOR_URL", { enumerable: true, get: fun Object.defineProperty(exports, "InternalError", { enumerable: true, get: function () { return sign_1.InternalError; } }); var tuf_1 = require("@sigstore/tuf"); Object.defineProperty(exports, "TUFError", { enumerable: true, get: function () { return tuf_1.TUFError; } }); -var error_1 = require("./error"); -Object.defineProperty(exports, "PolicyError", { enumerable: true, get: function () { return error_1.PolicyError; } }); -Object.defineProperty(exports, "VerificationError", { enumerable: true, get: function () { return error_1.VerificationError; } }); +var verify_1 = require("@sigstore/verify"); +Object.defineProperty(exports, "PolicyError", { enumerable: true, get: function () { return verify_1.PolicyError; } }); +Object.defineProperty(exports, "VerificationError", { enumerable: true, get: function () { return verify_1.VerificationError; } }); var sigstore_1 = require("./sigstore"); Object.defineProperty(exports, "attest", { enumerable: true, get: function () { return sigstore_1.attest; } }); Object.defineProperty(exports, "createVerifier", { enumerable: true, get: function () { return sigstore_1.createVerifier; } }); diff --git a/node_modules/sigstore/dist/sigstore.js b/node_modules/sigstore/dist/sigstore.js index 72770e4359f9e..3f6d895f84168 100644 --- a/node_modules/sigstore/dist/sigstore.js +++ b/node_modules/sigstore/dist/sigstore.js @@ -41,8 +41,8 @@ limitations under the License. */ const bundle_1 = require("@sigstore/bundle"); const tuf = __importStar(require("@sigstore/tuf")); +const verify_1 = require("@sigstore/verify"); const config = __importStar(require("./config")); -const verify_1 = require("./verify"); async function sign(payload, /* istanbul ignore next */ options = {}) { @@ -77,15 +77,26 @@ options = {}) { mirrorURL: options.tufMirrorURL, rootPath: options.tufRootPath, cachePath: options.tufCachePath, + forceCache: options.tufForceCache, retry: options.retry ?? config.DEFAULT_RETRY, timeout: options.timeout ?? config.DEFAULT_TIMEOUT, }); - const verifier = new verify_1.Verifier(trustedRoot, options.keySelector); - const verifyOpts = config.artifactVerificationOptions(options); + const keyFinder = options.keySelector + ? config.createKeyFinder(options.keySelector) + : undefined; + const trustMaterial = (0, verify_1.toTrustMaterial)(trustedRoot, keyFinder); + const verifierOptions = { + ctlogThreshold: options.ctLogThreshold, + tlogThreshold: options.tlogThreshold, + }; + const verifier = new verify_1.Verifier(trustMaterial, verifierOptions); + const policy = config.createVerificationPolicy(options); return { verify: (bundle, payload) => { const deserializedBundle = (0, bundle_1.bundleFromJSON)(bundle); - return verifier.verify(deserializedBundle, verifyOpts, payload); + const signedEntity = (0, verify_1.toSignedEntity)(deserializedBundle, payload); + verifier.verify(signedEntity, policy); + return; }, }; } diff --git a/node_modules/sigstore/dist/tlog/verify/body.js b/node_modules/sigstore/dist/tlog/verify/body.js deleted file mode 100644 index 5a265e5190c12..0000000000000 --- a/node_modules/sigstore/dist/tlog/verify/body.js +++ /dev/null @@ -1,152 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.verifyTLogBody = void 0; -/* -Copyright 2023 The Sigstore Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -const error_1 = require("../../error"); -const util_1 = require("../../util"); -const TLOG_MISMATCH_ERROR_MSG = 'bundle content and tlog entry do not match'; -// Compare the given tlog entry to the given bundle -function verifyTLogBody(entry, bundleContent) { - const { kind, version } = entry.kindVersion; - const body = JSON.parse(entry.canonicalizedBody.toString('utf8')); - try { - if (kind !== body.kind || version !== body.apiVersion) { - throw new error_1.VerificationError(TLOG_MISMATCH_ERROR_MSG); - } - switch (body.kind) { - case 'dsse': - verifyDSSETLogBody(body, bundleContent); - break; - case 'intoto': - verifyIntotoTLogBody(body, bundleContent); - break; - case 'hashedrekord': - verifyHashedRekordTLogBody(body, bundleContent); - break; - default: - throw new error_1.VerificationError(`unsupported kind in tlog entry: ${kind}`); - } - return true; - } - catch (e) { - return false; - } -} -exports.verifyTLogBody = verifyTLogBody; -// Compare the given intoto tlog entry to the given bundle -function verifyDSSETLogBody(tlogEntry, content) { - if (content?.$case !== 'dsseEnvelope') { - throw new error_1.VerificationError(`unsupported bundle content: ${content?.$case || 'unknown'}`); - } - const dsse = content.dsseEnvelope; - switch (tlogEntry.apiVersion) { - case '0.0.1': - verifyDSSE001TLogBody(tlogEntry, dsse); - break; - default: - throw new error_1.VerificationError(`unsupported dsse version: ${tlogEntry.apiVersion}`); - } -} -// Compare the given intoto tlog entry to the given bundle -function verifyIntotoTLogBody(tlogEntry, content) { - if (content?.$case !== 'dsseEnvelope') { - throw new error_1.VerificationError(`unsupported bundle content: ${content?.$case || 'unknown'}`); - } - const dsse = content.dsseEnvelope; - switch (tlogEntry.apiVersion) { - case '0.0.2': - verifyIntoto002TLogBody(tlogEntry, dsse); - break; - default: - throw new error_1.VerificationError(`unsupported intoto version: ${tlogEntry.apiVersion}`); - } -} -// Compare the given hashedrekord tlog entry to the given bundle -function verifyHashedRekordTLogBody(tlogEntry, content) { - if (content?.$case !== 'messageSignature') { - throw new error_1.VerificationError(`unsupported bundle content: ${content?.$case || 'unknown'}`); - } - const messageSignature = content.messageSignature; - switch (tlogEntry.apiVersion) { - case '0.0.1': - verifyHashedrekor001TLogBody(tlogEntry, messageSignature); - break; - default: - throw new error_1.VerificationError(`unsupported hashedrekord version: ${tlogEntry.apiVersion}`); - } -} -// Compare the given dsse v0.0.1 tlog entry to the given DSSE envelope. -function verifyDSSE001TLogBody(tlogEntry, dsse) { - // Collect all of the signatures from the DSSE envelope - // Turns them into base64-encoded strings for comparison - const dsseSigs = dsse.signatures.map((signature) => signature.sig.toString('base64')); - // Collect all of the signatures from the tlog entry - const tlogSigs = tlogEntry.spec.signatures?.map((signature) => signature.signature); - // Ensure the bundle's DSSE and the tlog entry contain the same number of signatures - if (dsseSigs.length !== tlogSigs?.length) { - throw new error_1.VerificationError(TLOG_MISMATCH_ERROR_MSG); - } - // Ensure that every signature in the bundle's DSSE is present in the tlog entry - if (!dsseSigs.every((dsseSig) => tlogSigs.includes(dsseSig))) { - throw new error_1.VerificationError(TLOG_MISMATCH_ERROR_MSG); - } - // Ensure the digest of the bundle's DSSE payload matches the digest in the - // tlog entry - const dssePayloadHash = util_1.crypto.hash(dsse.payload).toString('hex'); - if (dssePayloadHash !== tlogEntry.spec.payloadHash?.value) { - throw new error_1.VerificationError(TLOG_MISMATCH_ERROR_MSG); - } -} -// Compare the given intoto v0.0.2 tlog entry to the given DSSE envelope. -function verifyIntoto002TLogBody(tlogEntry, dsse) { - // Collect all of the signatures from the DSSE envelope - // Turns them into base64-encoded strings for comparison - const dsseSigs = dsse.signatures.map((signature) => signature.sig.toString('base64')); - // Collect all of the signatures from the tlog entry - // Remember that tlog signastures are double base64-encoded - const tlogSigs = tlogEntry.spec.content.envelope?.signatures.map((signature) => (signature.sig ? util_1.encoding.base64Decode(signature.sig) : '')); - // Ensure the bundle's DSSE and the tlog entry contain the same number of signatures - if (dsseSigs.length !== tlogSigs?.length) { - throw new error_1.VerificationError(TLOG_MISMATCH_ERROR_MSG); - } - // Ensure that every signature in the bundle's DSSE is present in the tlog entry - if (!dsseSigs.every((dsseSig) => tlogSigs.includes(dsseSig))) { - throw new error_1.VerificationError(TLOG_MISMATCH_ERROR_MSG); - } - // Ensure the digest of the bundle's DSSE payload matches the digest in the - // tlog entry - const dssePayloadHash = util_1.crypto.hash(dsse.payload).toString('hex'); - if (dssePayloadHash !== tlogEntry.spec.content.payloadHash?.value) { - throw new error_1.VerificationError(TLOG_MISMATCH_ERROR_MSG); - } -} -// Compare the given hashedrekord v0.0.1 tlog entry to the given message -// signature -function verifyHashedrekor001TLogBody(tlogEntry, messageSignature) { - // Ensure that the bundles message signature matches the tlog entry - const msgSig = messageSignature.signature.toString('base64'); - const tlogSig = tlogEntry.spec.signature.content; - if (msgSig !== tlogSig) { - throw new error_1.VerificationError(TLOG_MISMATCH_ERROR_MSG); - } - // Ensure that the bundle's message digest matches the tlog entry - const msgDigest = messageSignature.messageDigest?.digest.toString('hex'); - const tlogDigest = tlogEntry.spec.data.hash?.value; - if (msgDigest !== tlogDigest) { - throw new error_1.VerificationError(TLOG_MISMATCH_ERROR_MSG); - } -} diff --git a/node_modules/sigstore/dist/tlog/verify/index.js b/node_modules/sigstore/dist/tlog/verify/index.js deleted file mode 100644 index 9224feffde00b..0000000000000 --- a/node_modules/sigstore/dist/tlog/verify/index.js +++ /dev/null @@ -1,92 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.verifyTLogEntries = void 0; -/* -Copyright 2023 The Sigstore Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -const bundle_1 = require("@sigstore/bundle"); -const error_1 = require("../../error"); -const cert_1 = require("../../x509/cert"); -const body_1 = require("./body"); -const checkpoint_1 = require("./checkpoint"); -const merkle_1 = require("./merkle"); -const set_1 = require("./set"); -// Verifies that the number of tlog entries that pass offline verification -// is greater than or equal to the threshold specified in the options. -function verifyTLogEntries(bundle, trustedRoot, options) { - if (bundle.mediaType === bundle_1.BUNDLE_V01_MEDIA_TYPE) { - (0, bundle_1.assertBundleV01)(bundle); - verifyTLogEntriesForBundleV01(bundle, trustedRoot, options); - } - else { - (0, bundle_1.assertBundleLatest)(bundle); - verifyTLogEntriesForBundleLatest(bundle, trustedRoot, options); - } -} -exports.verifyTLogEntries = verifyTLogEntries; -function verifyTLogEntriesForBundleV01(bundle, trustedRoot, options) { - if (options.performOnlineVerification) { - throw new error_1.VerificationError('Online verification not implemented'); - } - // Extract the signing cert, if available - const signingCert = signingCertificate(bundle); - // Iterate over the tlog entries and verify each one - const verifiedEntries = bundle.verificationMaterial.tlogEntries.filter((entry) => verifyTLogEntryWithInclusionPromise(entry, bundle.content, trustedRoot.tlogs, signingCert)); - if (verifiedEntries.length < options.threshold) { - throw new error_1.VerificationError('tlog verification failed'); - } -} -function verifyTLogEntriesForBundleLatest(bundle, trustedRoot, options) { - if (options.performOnlineVerification) { - throw new error_1.VerificationError('Online verification not implemented'); - } - // Extract the signing cert, if available - const signingCert = signingCertificate(bundle); - // Iterate over the tlog entries and verify each one - const verifiedEntries = bundle.verificationMaterial.tlogEntries.filter((entry) => verifyTLogEntryWithInclusionProof(entry, bundle.content, trustedRoot.tlogs, signingCert)); - if (verifiedEntries.length < options.threshold) { - throw new error_1.VerificationError('tlog verification failed'); - } -} -function verifyTLogEntryWithInclusionPromise(entry, bundleContent, tlogs, signingCert) { - // If there is a signing certificate availble, check that the tlog integrated - // time is within the certificate's validity period; otherwise, skip this - // check. - const verifyTLogIntegrationTime = signingCert - ? () => signingCert.validForDate(new Date(Number(entry.integratedTime) * 1000)) - : () => true; - return ((0, body_1.verifyTLogBody)(entry, bundleContent) && - (0, set_1.verifyTLogSET)(entry, tlogs) && - verifyTLogIntegrationTime()); -} -function verifyTLogEntryWithInclusionProof(entry, bundleContent, tlogs, signingCert) { - // If there is a signing certificate availble, check that the tlog integrated - // time is within the certificate's validity period; otherwise, skip this - // check. - const verifyTLogIntegrationTime = signingCert - ? () => signingCert.validForDate(new Date(Number(entry.integratedTime) * 1000)) - : () => true; - return ((0, body_1.verifyTLogBody)(entry, bundleContent) && - (0, merkle_1.verifyMerkleInclusion)(entry) && - (0, checkpoint_1.verifyCheckpoint)(entry, tlogs) && - verifyTLogIntegrationTime()); -} -function signingCertificate(bundle) { - if (!(0, bundle_1.isBundleWithCertificateChain)(bundle)) { - return undefined; - } - const signingCert = bundle.verificationMaterial.content.x509CertificateChain.certificates[0]; - return cert_1.x509Certificate.parse(signingCert.rawBytes); -} diff --git a/node_modules/sigstore/dist/tlog/verify/set.js b/node_modules/sigstore/dist/tlog/verify/set.js deleted file mode 100644 index 959cd5883f1ca..0000000000000 --- a/node_modules/sigstore/dist/tlog/verify/set.js +++ /dev/null @@ -1,64 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.verifyTLogSET = void 0; -const util_1 = require("../../util"); -// Verifies the SET for the given entry against the list of trusted -// transparency logs. Returns true if the SET can be verified against at least -// one of the trusted logs; otherwise, returns false. -function verifyTLogSET(entry, tlogs) { - // Filter the list of tlog instances to only those which might be able to - // verify the SET - const validTLogs = filterTLogInstances(tlogs, entry.logId.keyId, entry.integratedTime); - // Check to see if we can verify the SET against any of the valid tlogs - return validTLogs.some((tlog) => { - const publicKey = util_1.crypto.createPublicKey(tlog.publicKey.rawBytes); - // Re-create the original Rekor verification payload - const payload = toVerificationPayload(entry); - // Canonicalize the payload and turn into a buffer for verification - const data = Buffer.from(util_1.json.canonicalize(payload), 'utf8'); - // Extract the SET from the tlog entry - const signature = entry.inclusionPromise.signedEntryTimestamp; - return util_1.crypto.verifyBlob(data, publicKey, signature); - }); -} -exports.verifyTLogSET = verifyTLogSET; -// Returns a properly formatted "VerificationPayload" for one of the -// transaction log entires in the given bundle which can be used for SET -// verification. -function toVerificationPayload(entry) { - const { integratedTime, logIndex, logId, canonicalizedBody } = entry; - return { - body: canonicalizedBody.toString('base64'), - integratedTime: Number(integratedTime), - logIndex: Number(logIndex), - logID: logId.keyId.toString('hex'), - }; -} -// Filter the list of tlog instances to only those which match the given log -// ID and have public keys which are valid for the given integrated time. -function filterTLogInstances(tlogInstances, logID, integratedTime) { - const targetDate = new Date(Number(integratedTime) * 1000); - return tlogInstances.filter((tlog) => { - // If the log IDs don't match, we can't use this tlog - if (!tlog.logId?.keyId.equals(logID)) { - return false; - } - // If the tlog doesn't have a public key, we can't use it - const publicKey = tlog.publicKey; - if (publicKey === undefined) { - return false; - } - // If the tlog doesn't have a rawBytes field, we can't use it - if (publicKey.rawBytes === undefined) { - return false; - } - // If the tlog doesn't have a validFor field, we don't need to check it - if (publicKey.validFor === undefined) { - return true; - } - // Check that the integrated time is within the validFor range - return (publicKey.validFor.start !== undefined && - publicKey.validFor.start <= targetDate && - (!publicKey.validFor.end || targetDate <= publicKey.validFor.end)); - }); -} diff --git a/node_modules/sigstore/dist/types/sigstore.js b/node_modules/sigstore/dist/types/sigstore.js deleted file mode 100644 index 36efb67e38a5e..0000000000000 --- a/node_modules/sigstore/dist/types/sigstore.js +++ /dev/null @@ -1,27 +0,0 @@ -"use strict"; -/* -Copyright 2023 The Sigstore Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -Object.defineProperty(exports, "__esModule", { value: true }); -exports.isCAVerificationOptions = exports.SubjectAlternativeNameType = void 0; -// Enums from protobuf-specs -var protobuf_specs_1 = require("@sigstore/protobuf-specs"); -Object.defineProperty(exports, "SubjectAlternativeNameType", { enumerable: true, get: function () { return protobuf_specs_1.SubjectAlternativeNameType; } }); -function isCAVerificationOptions(options) { - return (options.ctlogOptions !== undefined && - (options.signers === undefined || - options.signers.$case === 'certificateIdentities')); -} -exports.isCAVerificationOptions = isCAVerificationOptions; diff --git a/node_modules/sigstore/dist/util/dsse.js b/node_modules/sigstore/dist/util/dsse.js deleted file mode 100644 index bba7baa6bbfb8..0000000000000 --- a/node_modules/sigstore/dist/util/dsse.js +++ /dev/null @@ -1,25 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.preAuthEncoding = void 0; -/* -Copyright 2022 The Sigstore Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -const PAE_PREFIX = 'DSSEv1'; -// DSSE Pre-Authentication Encoding -function preAuthEncoding(payloadType, payload) { - const prefix = Buffer.from(`${PAE_PREFIX} ${payloadType.length} ${payloadType} ${payload.length} `, 'ascii'); - return Buffer.concat([prefix, payload]); -} -exports.preAuthEncoding = preAuthEncoding; diff --git a/node_modules/sigstore/dist/util/encoding.js b/node_modules/sigstore/dist/util/encoding.js deleted file mode 100644 index 8674d779b61f9..0000000000000 --- a/node_modules/sigstore/dist/util/encoding.js +++ /dev/null @@ -1,46 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.base64URLUnescape = exports.base64URLEscape = exports.base64URLDecode = exports.base64URLEncode = exports.base64Decode = exports.base64Encode = void 0; -/* -Copyright 2022 The Sigstore Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -const BASE64_ENCODING = 'base64'; -const UTF8_ENCODING = 'utf-8'; -function base64Encode(str) { - return Buffer.from(str, UTF8_ENCODING).toString(BASE64_ENCODING); -} -exports.base64Encode = base64Encode; -function base64Decode(str) { - return Buffer.from(str, BASE64_ENCODING).toString(UTF8_ENCODING); -} -exports.base64Decode = base64Decode; -function base64URLEncode(str) { - return base64URLEscape(base64Encode(str)); -} -exports.base64URLEncode = base64URLEncode; -function base64URLDecode(str) { - return base64Decode(base64URLUnescape(str)); -} -exports.base64URLDecode = base64URLDecode; -function base64URLEscape(str) { - return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, ''); -} -exports.base64URLEscape = base64URLEscape; -function base64URLUnescape(str) { - // Repad the base64 string if necessary - str += '='.repeat((4 - (str.length % 4)) % 4); - return str.replace(/-/g, '+').replace(/_/g, '/'); -} -exports.base64URLUnescape = base64URLUnescape; diff --git a/node_modules/sigstore/dist/verify.js b/node_modules/sigstore/dist/verify.js deleted file mode 100644 index a3dc4b307e495..0000000000000 --- a/node_modules/sigstore/dist/verify.js +++ /dev/null @@ -1,160 +0,0 @@ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Verifier = void 0; -/* -Copyright 2023 The Sigstore Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -const bundle_1 = require("@sigstore/bundle"); -const ca = __importStar(require("./ca/verify")); -const error_1 = require("./error"); -const tlog = __importStar(require("./tlog/verify")); -const sigstore = __importStar(require("./types/sigstore")); -const util_1 = require("./util"); -class Verifier { - constructor(trustedRoot, keySelector) { - this.trustedRoot = trustedRoot; - this.keySelector = keySelector || (() => undefined); - } - // Verifies the bundle signature, the bundle's certificate chain (if present) - // and the bundle's transparency log entries. - verify(bundle, options, data) { - this.verifyArtifactSignature(bundle, data); - if ((0, bundle_1.isBundleWithCertificateChain)(bundle)) { - this.verifySigningCertificate(bundle, options); - } - if (options.tlogOptions.disable === false) { - this.verifyTLogEntries(bundle, options); - } - } - // Performs bundle signature verification. Determines the type of the bundle - // content and delegates to the appropriate signature verification function. - verifyArtifactSignature(bundle, data) { - const publicKey = this.getPublicKey(bundle); - switch (bundle.content?.$case) { - case 'messageSignature': - if (!data) { - throw new error_1.VerificationError('no data provided for message signature verification'); - } - verifyMessageSignature(data, bundle.content.messageSignature, publicKey); - break; - case 'dsseEnvelope': - verifyDSSESignature(bundle.content.dsseEnvelope, publicKey); - break; - } - } - // Performs verification of the bundle's certificate chain. The bundle must - // contain a certificate chain and the options must contain the required - // options for CA verification. - // TODO: We've temporarily removed the requirement that the options contain - // the list of trusted signer identities. This will be added back in a future - // release. - verifySigningCertificate(bundle, options) { - if (!sigstore.isCAVerificationOptions(options)) { - throw new error_1.VerificationError('no trusted certificates provided for verification'); - } - ca.verifySigningCertificate(bundle, this.trustedRoot, options); - } - // Performs verification of the bundle's transparency log entries. The bundle - // must contain a list of transparency log entries. - verifyTLogEntries(bundle, options) { - tlog.verifyTLogEntries(bundle, this.trustedRoot, options.tlogOptions); - } - // Returns the public key which will be used to verify the bundle signature. - // The public key is selected based on the verification material in the bundle - // and the options provided. - getPublicKey(bundle) { - // Select the key which will be used to verify the signature - switch (bundle.verificationMaterial?.content?.$case) { - // If the bundle contains a certificate chain, the public key is the - // first certificate in the chain (the signing certificate) - case 'x509CertificateChain': - return getPublicKeyFromCertificateChain(bundle.verificationMaterial.content.x509CertificateChain); - // If the bundle contains a public key hint, the public key is selected - // from the list of trusted keys in the options - case 'publicKey': - return getPublicKeyFromHint(bundle.verificationMaterial.content.publicKey, this.keySelector); - } - } -} -exports.Verifier = Verifier; -// Retrieves the public key from the first certificate in the certificate chain -function getPublicKeyFromCertificateChain(certificateChain) { - const cert = util_1.pem.fromDER(certificateChain.certificates[0].rawBytes); - return util_1.crypto.createPublicKey(cert); -} -// Retrieves the public key through the key selector callback, passing the -// public key hint from the bundle -function getPublicKeyFromHint(publicKeyID, keySelector) { - const key = keySelector(publicKeyID.hint); - if (!key) { - throw new error_1.VerificationError('no public key found for signature verification'); - } - try { - return util_1.crypto.createPublicKey(key); - } - catch (e) { - throw new error_1.VerificationError('invalid public key'); - } -} -// Performs signature verification for bundle containing a message signature. -// Verifies that the digest and signature found in the bundle match the -// provided data. -function verifyMessageSignature(data, messageSignature, publicKey) { - // Extract signature for message - const { signature, messageDigest } = messageSignature; - const calculatedDigest = util_1.crypto.hash(data); - if (!calculatedDigest.equals(messageDigest.digest)) { - throw new error_1.VerificationError('message digest verification failed'); - } - if (!util_1.crypto.verifyBlob(data, publicKey, signature)) { - throw new error_1.VerificationError('artifact signature verification failed'); - } -} -// Performs signature verification for bundle containing a DSSE envelope. -// Calculates the PAE for the DSSE envelope and verifies it against the -// signature in the envelope. -function verifyDSSESignature(envelope, publicKey) { - // Construct payload over which the signature was originally created - const { payloadType, payload } = envelope; - const data = util_1.dsse.preAuthEncoding(payloadType, payload); - // Only support a single signature in DSSE - const signature = envelope.signatures[0].sig; - if (!util_1.crypto.verifyBlob(data, publicKey, signature)) { - throw new error_1.VerificationError('artifact signature verification failed'); - } -} diff --git a/node_modules/sigstore/package.json b/node_modules/sigstore/package.json index daf50ba601884..bbc619e3be3c1 100644 --- a/node_modules/sigstore/package.json +++ b/node_modules/sigstore/package.json @@ -1,6 +1,6 @@ { "name": "sigstore", - "version": "2.1.0", + "version": "2.2.0", "description": "code-signing for npm packages", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -29,15 +29,17 @@ "devDependencies": { "@sigstore/rekor-types": "^2.0.0", "@sigstore/jest": "^0.0.0", - "@sigstore/mock": "^0.4.0", + "@sigstore/mock": "^0.6.3", "@tufjs/repo-mock": "^2.0.0", - "@types/make-fetch-happen": "^10.0.0" + "@types/make-fetch-happen": "^10.0.4" }, "dependencies": { - "@sigstore/bundle": "^2.1.0", + "@sigstore/bundle": "^2.1.1", + "@sigstore/core": "^0.2.0", "@sigstore/protobuf-specs": "^0.2.1", - "@sigstore/sign": "^2.1.0", - "@sigstore/tuf": "^2.1.0" + "@sigstore/sign": "^2.2.1", + "@sigstore/tuf": "^2.3.0", + "@sigstore/verify": "^0.1.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" diff --git a/package-lock.json b/package-lock.json index f6f44e3cc285b..16ca04ca5e66f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2125,9 +2125,9 @@ } }, "node_modules/@sigstore/bundle": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.1.0.tgz", - "integrity": "sha512-89uOo6yh/oxaU8AeOUnVrTdVMcGk9Q1hJa7Hkvalc6G3Z3CupWk4Xe9djSgJm9fMkH69s0P0cVHUoKSOemLdng==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.1.1.tgz", + "integrity": "sha512-v3/iS+1nufZdKQ5iAlQKcCsoh0jffQyABvYIxKsZQFWc4ubuGjwZklFHpDgV6O6T7vvV78SW5NHI91HFKEcxKg==", "inBundle": true, "dependencies": { "@sigstore/protobuf-specs": "^0.2.1" @@ -2136,6 +2136,15 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/@sigstore/core": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@sigstore/core/-/core-0.2.0.tgz", + "integrity": "sha512-THobAPPZR9pDH2CAvDLpkrYedt7BlZnsyxDe+Isq4ZmGfPy5juOFZq487vCU2EgKD7aHSiTfE/i7sN7aEdzQnA==", + "inBundle": true, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, "node_modules/@sigstore/protobuf-specs": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz", @@ -2146,12 +2155,13 @@ } }, "node_modules/@sigstore/sign": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-2.2.0.tgz", - "integrity": "sha512-AAbmnEHDQv6CSfrWA5wXslGtzLPtAtHZleKOgxdQYvx/s76Fk6T6ZVt7w2IGV9j1UrFeBocTTQxaXG2oRrDhYA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-2.2.1.tgz", + "integrity": "sha512-U5sKQEj+faE1MsnLou1f4DQQHeFZay+V9s9768lw48J4pKykPj34rWyI1lsMOGJ3Mae47Ye6q3HAJvgXO21rkQ==", "inBundle": true, "dependencies": { - "@sigstore/bundle": "^2.1.0", + "@sigstore/bundle": "^2.1.1", + "@sigstore/core": "^0.2.0", "@sigstore/protobuf-specs": "^0.2.1", "make-fetch-happen": "^13.0.0" }, @@ -2172,6 +2182,20 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/@sigstore/verify": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/verify/-/verify-0.1.0.tgz", + "integrity": "sha512-2UzMNYAa/uaz11NhvgRnIQf4gpLTJ59bhb8ESXaoSS5sxedfS+eLak8bsdMc+qpNQfITUTFoSKFx5h8umlRRiA==", + "inBundle": true, + "dependencies": { + "@sigstore/bundle": "^2.1.1", + "@sigstore/core": "^0.2.0", + "@sigstore/protobuf-specs": "^0.2.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -12203,15 +12227,17 @@ } }, "node_modules/sigstore": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.1.0.tgz", - "integrity": "sha512-kPIj+ZLkyI3QaM0qX8V/nSsweYND3W448pwkDgS6CQ74MfhEkIR8ToK5Iyx46KJYRjseVcD3Rp9zAmUAj6ZjPw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-2.2.0.tgz", + "integrity": "sha512-fcU9clHwEss2/M/11FFM8Jwc4PjBgbhXoNskoK5guoK0qGQBSeUbQZRJ+B2fDFIvhyf0gqCaPrel9mszbhAxug==", "inBundle": true, "dependencies": { - "@sigstore/bundle": "^2.1.0", + "@sigstore/bundle": "^2.1.1", + "@sigstore/core": "^0.2.0", "@sigstore/protobuf-specs": "^0.2.1", - "@sigstore/sign": "^2.1.0", - "@sigstore/tuf": "^2.1.0" + "@sigstore/sign": "^2.2.1", + "@sigstore/tuf": "^2.3.0", + "@sigstore/verify": "^0.1.0" }, "engines": { "node": "^16.14.0 || >=18.0.0" @@ -16414,7 +16440,7 @@ "npm-registry-fetch": "^16.0.0", "proc-log": "^3.0.0", "semver": "^7.3.7", - "sigstore": "^2.1.0", + "sigstore": "^2.2.0", "ssri": "^10.0.5" }, "devDependencies": { diff --git a/workspaces/libnpmpublish/package.json b/workspaces/libnpmpublish/package.json index ce2982450249c..8d5240cf1f744 100644 --- a/workspaces/libnpmpublish/package.json +++ b/workspaces/libnpmpublish/package.json @@ -44,7 +44,7 @@ "npm-registry-fetch": "^16.0.0", "proc-log": "^3.0.0", "semver": "^7.3.7", - "sigstore": "^2.1.0", + "sigstore": "^2.2.0", "ssri": "^10.0.5" }, "engines": {