tsa.js 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  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, {
  12. start: signingTime,
  13. end: signingTime,
  14. });
  15. // Filter for CAs which match serial and issuer embedded in the timestamp
  16. timestampAuthorities = filterCAsBySerialAndIssuer(timestampAuthorities, {
  17. serialNumber: timestamp.signerSerialNumber,
  18. issuer: timestamp.signerIssuer,
  19. });
  20. // Check that we can verify the timestamp with AT LEAST ONE of the remaining
  21. // CAs
  22. const verified = timestampAuthorities.some((ca) => {
  23. try {
  24. verifyTimestampForCA(timestamp, data, ca);
  25. return true;
  26. }
  27. catch (e) {
  28. return false;
  29. }
  30. });
  31. if (!verified) {
  32. throw new error_1.VerificationError({
  33. code: 'TIMESTAMP_ERROR',
  34. message: 'timestamp could not be verified',
  35. });
  36. }
  37. }
  38. function verifyTimestampForCA(timestamp, data, ca) {
  39. const [leaf, ...cas] = ca.certChain;
  40. const signingKey = core_1.crypto.createPublicKey(leaf.publicKey);
  41. const signingTime = timestamp.signingTime;
  42. // Verify the certificate chain for the provided CA
  43. try {
  44. new certificate_1.CertificateChainVerifier({
  45. untrustedCert: leaf,
  46. trustedCerts: cas,
  47. }).verify();
  48. }
  49. catch (e) {
  50. throw new error_1.VerificationError({
  51. code: 'TIMESTAMP_ERROR',
  52. message: 'invalid certificate chain',
  53. });
  54. }
  55. // Check that all of the CA certs were valid at the time of signing
  56. const validAtSigningTime = ca.certChain.every((cert) => cert.validForDate(signingTime));
  57. if (!validAtSigningTime) {
  58. throw new error_1.VerificationError({
  59. code: 'TIMESTAMP_ERROR',
  60. message: 'timestamp was signed with an expired certificate',
  61. });
  62. }
  63. // Check that the signing certificate's key can be used to verify the
  64. // timestamp signature.
  65. timestamp.verify(data, signingKey);
  66. }
  67. // Filters the list of CAs to those which have a leaf signing certificate which
  68. // matches the given serial number and issuer.
  69. function filterCAsBySerialAndIssuer(timestampAuthorities, criteria) {
  70. return timestampAuthorities.filter((ca) => ca.certChain.length > 0 &&
  71. core_1.crypto.bufferEqual(ca.certChain[0].serialNumber, criteria.serialNumber) &&
  72. core_1.crypto.bufferEqual(ca.certChain[0].issuer, criteria.issuer));
  73. }