def as_signing_certificate(cert: x509.Certificate) -> tsp.SigningCertificate: """ Format an ASN.1 ``SigningCertificate`` object, where the certificate is identified by its SHA-1 digest. :param cert: An X.509 certificate. :return: A :class:`tsp.SigningCertificate` object referring to the original certificate. """ # see RFC 2634, § 5.4.1 return tsp.SigningCertificate({ 'certs': [ tsp.ESSCertID({ 'cert_hash': hashlib.sha1(cert.dump()).digest(), 'issuer_serial': { 'issuer': [x509.GeneralName({'directory_name': cert.issuer})], 'serial_number': cert['tbs_certificate']['serial_number'] } }) ] })
def as_signing_certificate(cert: x509.Certificate) -> tsp.SigningCertificate: # see RFC 2634, § 5.4.1 return tsp.SigningCertificate({ 'certs': [tsp.ESSCertID({'cert_hash': hashlib.sha1(cert.dump()).digest()})] })
def request_tsa_response(self, req: tsp.TimeStampReq) -> tsp.TimeStampResp: # We pretend that certReq is always true in the request status = tsp.PKIStatusInfo({'status': tsp.PKIStatus('granted')}) message_imprint: tsp.MessageImprint = req['message_imprint'] md_algorithm = self.md_algorithm digest_algorithm_obj = algos.DigestAlgorithm({ 'algorithm': md_algorithm }) dt = self.fixed_dt or datetime.now(tz=tzlocal.get_localzone()) tst_info = { 'version': 'v1', 'policy': self.policy, 'message_imprint': message_imprint, 'serial_number': get_nonce(), 'gen_time': dt, 'tsa': x509.GeneralName( name='directory_name', value=self.tsa_cert.subject ) } try: tst_info['nonce'] = req['nonce'] except KeyError: pass tst_info = tsp.TSTInfo(tst_info) tst_info_data = tst_info.dump() message_digest = getattr(hashlib, md_algorithm)(tst_info_data).digest() signing_cert_id = tsp.ESSCertID({ 'cert_hash': hashlib.sha1(self.tsa_cert.dump()).digest() }) signed_attrs = cms.CMSAttributes([ simple_cms_attribute('content_type', 'tst_info'), simple_cms_attribute( 'signing_time', cms.Time({'utc_time': core.UTCTime(dt)}) ), simple_cms_attribute( 'signing_certificate', tsp.SigningCertificate({'certs': [signing_cert_id]}) ), simple_cms_attribute('message_digest', message_digest), ]) signature = generic_sign( self.tsa_key, signed_attrs.dump(), self.signature_algo ) sig_info = cms.SignerInfo({ 'version': 'v1', 'sid': cms.SignerIdentifier({ 'issuer_and_serial_number': cms.IssuerAndSerialNumber({ 'issuer': self.tsa_cert.issuer, 'serial_number': self.tsa_cert.serial_number, }) }), 'digest_algorithm': digest_algorithm_obj, 'signature_algorithm': self.signature_algo, 'signed_attrs': signed_attrs, 'signature': signature }) certs = set(self.certs_to_embed) certs.add(self.tsa_cert) signed_data = { # must use v3 to get access to the EncapsulatedContentInfo construct 'version': 'v3', 'digest_algorithms': cms.DigestAlgorithms((digest_algorithm_obj,)), 'encap_content_info': cms.EncapsulatedContentInfo({ 'content_type': cms.ContentType('tst_info'), 'content': cms.ParsableOctetString(tst_info_data) }), 'certificates': certs, 'signer_infos': [sig_info] } tst = cms.ContentInfo({ 'content_type': cms.ContentType('signed_data'), 'content': cms.SignedData(signed_data) }) return tsp.TimeStampResp({'status': status, 'time_stamp_token': tst})