1"use strict"; 2var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 if (k2 === undefined) k2 = k; 4 var desc = Object.getOwnPropertyDescriptor(m, k); 5 if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 desc = { enumerable: true, get: function() { return m[k]; } }; 7 } 8 Object.defineProperty(o, k2, desc); 9}) : (function(o, m, k, k2) { 10 if (k2 === undefined) k2 = k; 11 o[k2] = m[k]; 12})); 13var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 Object.defineProperty(o, "default", { enumerable: true, value: v }); 15}) : function(o, v) { 16 o["default"] = v; 17}); 18var __importStar = (this && this.__importStar) || function (mod) { 19 if (mod && mod.__esModule) return mod; 20 var result = {}; 21 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 __setModuleDefault(result, mod); 23 return result; 24}; 25Object.defineProperty(exports, "__esModule", { value: true }); 26exports.RFC3161Timestamp = void 0; 27/* 28Copyright 2023 The Sigstore Authors. 29 30Licensed under the Apache License, Version 2.0 (the "License"); 31you may not use this file except in compliance with the License. 32You may obtain a copy of the License at 33 34 http://www.apache.org/licenses/LICENSE-2.0 35 36Unless required by applicable law or agreed to in writing, software 37distributed under the License is distributed on an "AS IS" BASIS, 38WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 39See the License for the specific language governing permissions and 40limitations under the License. 41*/ 42const asn1_1 = require("../asn1"); 43const crypto = __importStar(require("../crypto")); 44const oid_1 = require("../oid"); 45const error_1 = require("./error"); 46const tstinfo_1 = require("./tstinfo"); 47const OID_PKCS9_CONTENT_TYPE_SIGNED_DATA = '1.2.840.113549.1.7.2'; 48const OID_PKCS9_CONTENT_TYPE_TSTINFO = '1.2.840.113549.1.9.16.1.4'; 49const OID_PKCS9_MESSAGE_DIGEST_KEY = '1.2.840.113549.1.9.4'; 50class RFC3161Timestamp { 51 constructor(asn1) { 52 this.root = asn1; 53 } 54 static parse(der) { 55 const asn1 = asn1_1.ASN1Obj.parseBuffer(der); 56 return new RFC3161Timestamp(asn1); 57 } 58 get status() { 59 return this.pkiStatusInfoObj.subs[0].toInteger(); 60 } 61 get contentType() { 62 return this.contentTypeObj.toOID(); 63 } 64 get eContentType() { 65 return this.eContentTypeObj.toOID(); 66 } 67 get signingTime() { 68 return this.tstInfo.genTime; 69 } 70 get signerIssuer() { 71 return this.signerSidObj.subs[0].value; 72 } 73 get signerSerialNumber() { 74 return this.signerSidObj.subs[1].value; 75 } 76 get signerDigestAlgorithm() { 77 const oid = this.signerDigestAlgorithmObj.subs[0].toOID(); 78 return oid_1.SHA2_HASH_ALGOS[oid]; 79 } 80 get signatureAlgorithm() { 81 const oid = this.signatureAlgorithmObj.subs[0].toOID(); 82 return oid_1.ECDSA_SIGNATURE_ALGOS[oid]; 83 } 84 get signatureValue() { 85 return this.signatureValueObj.value; 86 } 87 get tstInfo() { 88 // Need to unpack tstInfo from an OCTET STRING 89 return new tstinfo_1.TSTInfo(this.eContentObj.subs[0].subs[0]); 90 } 91 verify(data, publicKey) { 92 if (!this.timeStampTokenObj) { 93 throw new error_1.RFC3161TimestampVerificationError('timeStampToken is missing'); 94 } 95 // Check for expected ContentInfo content type 96 if (this.contentType !== OID_PKCS9_CONTENT_TYPE_SIGNED_DATA) { 97 throw new error_1.RFC3161TimestampVerificationError(`incorrect content type: ${this.contentType}`); 98 } 99 // Check for expected encapsulated content type 100 if (this.eContentType !== OID_PKCS9_CONTENT_TYPE_TSTINFO) { 101 throw new error_1.RFC3161TimestampVerificationError(`incorrect encapsulated content type: ${this.eContentType}`); 102 } 103 // Check that the tstInfo references the correct artifact 104 this.tstInfo.verify(data); 105 // Check that the signed message digest matches the tstInfo 106 this.verifyMessageDigest(); 107 // Check that the signature is valid for the signed attributes 108 this.verifySignature(publicKey); 109 } 110 verifyMessageDigest() { 111 // Check that the tstInfo matches the signed data 112 const tstInfoDigest = crypto.digest(this.signerDigestAlgorithm, this.tstInfo.raw); 113 const expectedDigest = this.messageDigestAttributeObj.subs[1].subs[0].value; 114 if (!crypto.bufferEqual(tstInfoDigest, expectedDigest)) { 115 throw new error_1.RFC3161TimestampVerificationError('signed data does not match tstInfo'); 116 } 117 } 118 verifySignature(key) { 119 // Encode the signed attributes for verification 120 const signedAttrs = this.signedAttrsObj.toDER(); 121 signedAttrs[0] = 0x31; // Change context-specific tag to SET 122 // Check that the signature is valid for the signed attributes 123 const verified = crypto.verify(signedAttrs, key, this.signatureValue, this.signatureAlgorithm); 124 if (!verified) { 125 throw new error_1.RFC3161TimestampVerificationError('signature verification failed'); 126 } 127 } 128 // https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2 129 get pkiStatusInfoObj() { 130 // pkiStatusInfo is the first element of the timestamp response sequence 131 return this.root.subs[0]; 132 } 133 // https://www.rfc-editor.org/rfc/rfc3161#section-2.4.2 134 get timeStampTokenObj() { 135 // timeStampToken is the first element of the timestamp response sequence 136 return this.root.subs[1]; 137 } 138 // https://datatracker.ietf.org/doc/html/rfc5652#section-3 139 get contentTypeObj() { 140 return this.timeStampTokenObj.subs[0]; 141 } 142 // https://www.rfc-editor.org/rfc/rfc5652#section-3 143 get signedDataObj() { 144 const obj = this.timeStampTokenObj.subs.find((sub) => sub.tag.isContextSpecific(0x00)); 145 return obj.subs[0]; 146 } 147 // https://datatracker.ietf.org/doc/html/rfc5652#section-5.1 148 get encapContentInfoObj() { 149 return this.signedDataObj.subs[2]; 150 } 151 // https://datatracker.ietf.org/doc/html/rfc5652#section-5.1 152 get signerInfosObj() { 153 // SignerInfos is the last element of the signed data sequence 154 const sd = this.signedDataObj; 155 return sd.subs[sd.subs.length - 1]; 156 } 157 // https://www.rfc-editor.org/rfc/rfc5652#section-5.1 158 get signerInfoObj() { 159 // Only supporting one signer 160 return this.signerInfosObj.subs[0]; 161 } 162 // https://datatracker.ietf.org/doc/html/rfc5652#section-5.2 163 get eContentTypeObj() { 164 return this.encapContentInfoObj.subs[0]; 165 } 166 // https://datatracker.ietf.org/doc/html/rfc5652#section-5.2 167 get eContentObj() { 168 return this.encapContentInfoObj.subs[1]; 169 } 170 // https://datatracker.ietf.org/doc/html/rfc5652#section-5.3 171 get signedAttrsObj() { 172 const signedAttrs = this.signerInfoObj.subs.find((sub) => sub.tag.isContextSpecific(0x00)); 173 return signedAttrs; 174 } 175 // https://datatracker.ietf.org/doc/html/rfc5652#section-5.3 176 get messageDigestAttributeObj() { 177 const messageDigest = this.signedAttrsObj.subs.find((sub) => sub.subs[0].tag.isOID() && 178 sub.subs[0].toOID() === OID_PKCS9_MESSAGE_DIGEST_KEY); 179 return messageDigest; 180 } 181 // https://datatracker.ietf.org/doc/html/rfc5652#section-5.3 182 get signerSidObj() { 183 return this.signerInfoObj.subs[1]; 184 } 185 // https://datatracker.ietf.org/doc/html/rfc5652#section-5.3 186 get signerDigestAlgorithmObj() { 187 // Signature is the 2nd element of the signerInfoObj object 188 return this.signerInfoObj.subs[2]; 189 } 190 // https://datatracker.ietf.org/doc/html/rfc5652#section-5.3 191 get signatureAlgorithmObj() { 192 // Signature is the 4th element of the signerInfoObj object 193 return this.signerInfoObj.subs[4]; 194 } 195 // https://datatracker.ietf.org/doc/html/rfc5652#section-5.3 196 get signatureValueObj() { 197 // Signature is the 6th element of the signerInfoObj object 198 return this.signerInfoObj.subs[5]; 199 } 200} 201exports.RFC3161Timestamp = RFC3161Timestamp; 202