tsa.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.verifyRFC3161Timestamp = verifyRFC3161Timestamp;
  4. const core_1 = require("@sigstore/core");
  5. const error_1 = require("../error");
  6. const certificate_1 = require("../key/certificate");
  7. const trust_1 = require("../trust");
  8. function verifyRFC3161Timestamp(timestamp, data, timestampAuthorities) {
  9. const signingTime = timestamp.signingTime;
  10. // Filter for CAs which were valid at the time of signing
  11. timestampAuthorities = (0, trust_1.filterCertAuthorities)(timestampAuthorities, signingTime);
  12. // Filter for CAs which match serial and issuer embedded in the timestamp
  13. timestampAuthorities = filterCAsBySerialAndIssuer(timestampAuthorities, {
  14. serialNumber: timestamp.signerSerialNumber,
  15. issuer: timestamp.signerIssuer,
  16. });
  17. // Check that we can verify the timestamp with AT LEAST ONE of the remaining
  18. // CAs
  19. const verified = timestampAuthorities.some((ca) => {
  20. try {
  21. verifyTimestampForCA(timestamp, data, ca);
  22. return true;
  23. }
  24. catch (e) {
  25. return false;
  26. }
  27. });
  28. if (!verified) {
  29. throw new error_1.VerificationError({
  30. code: 'TIMESTAMP_ERROR',
  31. message: 'timestamp could not be verified',
  32. });
  33. }
  34. }
  35. function verifyTimestampForCA(timestamp, data, ca) {
  36. const [leaf, ...cas] = ca.certChain;
  37. const signingKey = core_1.crypto.createPublicKey(leaf.publicKey);
  38. const signingTime = timestamp.signingTime;
  39. // Verify the certificate chain for the provided CA
  40. try {
  41. new certificate_1.CertificateChainVerifier({
  42. untrustedCert: leaf,
  43. trustedCerts: cas,
  44. timestamp: signingTime,
  45. }).verify();
  46. }
  47. catch (e) {
  48. throw new error_1.VerificationError({
  49. code: 'TIMESTAMP_ERROR',
  50. message: 'invalid certificate chain',
  51. });
  52. }
  53. // Check that the signing certificate's key can be used to verify the
  54. // timestamp signature.
  55. timestamp.verify(data, signingKey);
  56. }
  57. // Filters the list of CAs to those which have a leaf signing certificate which
  58. // matches the given serial number and issuer.
  59. function filterCAsBySerialAndIssuer(timestampAuthorities, criteria) {
  60. return timestampAuthorities.filter((ca) => ca.certChain.length > 0 &&
  61. core_1.crypto.bufferEqual(ca.certChain[0].serialNumber, criteria.serialNumber) &&
  62. core_1.crypto.bufferEqual(ca.certChain[0].issuer, criteria.issuer));
  63. }