def compress_message(data_to_compress): """Function compresses data and returns the generated ASN.1 :param data_to_compress: A byte string of the data to be compressed :return: A CMS ASN.1 byte string of the compressed data. """ compressed_content = cms.ParsableOctetString( zlib.compress(data_to_compress)) return cms.ContentInfo({ 'content_type': cms.ContentType('compressed_data'), 'content': cms.CompressedData({ 'version': cms.CMSVersion('v0'), 'compression_algorithm': cms.CompressionAlgorithm( {'algorithm': cms.CompressionAlgorithmId('zlib')}), 'encap_content_info': cms.EncapsulatedContentInfo({ 'content_type': cms.ContentType('data'), 'content': compressed_content }) }) }).dump()
def compress_message(data_to_compress): """Function compresses data and returns the generated ASN.1 :param data_to_compress: A byte string of the data to be compressed :return: A CMS ASN.1 byte string of the compressed data. """ compressed_content = cms.ParsableOctetString( zlib.compress(data_to_compress)) return cms.ContentInfo({ "content_type": cms.ContentType("compressed_data"), "content": cms.CompressedData({ "version": cms.CMSVersion("v0"), "compression_algorithm": cms.CompressionAlgorithm( {"algorithm": cms.CompressionAlgorithmId("zlib")}), "encap_content_info": cms.EncapsulatedContentInfo({ "content_type": cms.ContentType("data"), "content": compressed_content, }), }), }).dump()
def compress_message(data_to_compress): compressed_content = cms.ParsableOctetString( zlib.compress(data_to_compress)) return cms.ContentInfo({ 'content_type': cms.ContentType('compressed_data'), 'content': cms.CompressedData({ 'version': cms.CMSVersion(0), 'compression_algorithm': cms.CompressionAlgorithm( {'algorithm': cms.CompressionAlgorithmId('zlib')}), 'encap_content_info': cms.EncapsulatedContentInfo({ 'content_type': cms.ContentType('data'), 'content': compressed_content }) }) })
def request_tsa_response(self, req: tsp.TimeStampReq) -> tsp.TimeStampResp: # We pretend that certReq is always true in the request # TODO generalise my detached signature logic to include cases like this # (see § 5.4 in RFC 5652) # TODO does the RFC status = tsp.PKIStatusInfo({'status': tsp.PKIStatus('granted')}) message_imprint: tsp.MessageImprint = req['message_imprint'] md_algorithm = message_imprint['hash_algorithm']['algorithm'].native digest_algorithm_obj = algos.DigestAlgorithm({ 'algorithm': md_algorithm }) dt = self.fixed_dt or datetime.now(tz=tzlocal.get_localzone()) tst_info = { 'version': 'v1', # See http://oidref.com/1.3.6.1.4.1.4146.2.2 # I don't really care too much, this is a testing device anyway 'policy': tsp.ObjectIdentifier('1.3.6.1.4.1.4146.2.2'), 'message_imprint': message_imprint, # should be sufficiently random (again, this is a testing class) '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() 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', general.as_signing_certificate(self.tsa_cert) ), simple_cms_attribute('message_digest', message_digest), ]) signature = asymmetric.rsa_pkcs1v15_sign( asymmetric.load_private_key(self.tsa_key), signed_attrs.dump(), md_algorithm ) 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': algos.SignedDigestAlgorithm( {'algorithm': 'rsassa_pkcs1v15'} ), '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})
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})
def request_tsa_response(self, req: tsp.TimeStampReq) \ -> tsp.TimeStampResp: # We pretend that certReq is always true in the request # TODO generalise my detached signature logic to include cases like this # (see § 5.4 in RFC 5652) # TODO does the RFC status = tsp.PKIStatusInfo({'status': tsp.PKIStatus('granted')}) message_imprint: tsp.MessageImprint = req['message_imprint'] md_algorithm = self.override_md if md_algorithm is None: md_algorithm = message_imprint['hash_algorithm'][ 'algorithm'].native digest_algorithm_obj = algos.DigestAlgorithm( {'algorithm': md_algorithm}) dt = self.fixed_dt or datetime.now(tz=tzlocal.get_localzone()) tst_info = { 'version': 'v1', # See http://oidref.com/1.3.6.1.4.1.4146.2.2 # I don't really care too much, this is a testing device anyway 'policy': tsp.ObjectIdentifier('1.3.6.1.4.1.4146.2.2'), 'message_imprint': message_imprint, # should be sufficiently random (again, this is a testing class) 'serial_number': get_nonce(), 'gen_time': dt, 'tsa': x509.GeneralName(name='directory_name', value=self.tsa_cert.subject) } if req['nonce'].native is not None: tst_info['nonce'] = req['nonce'] tst_info = tsp.TSTInfo(tst_info) tst_info_data = tst_info.dump() md_spec = get_pyca_cryptography_hash(md_algorithm) md = hashes.Hash(md_spec) md.update(tst_info_data) message_digest_value = md.finalize() 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', general.as_signing_certificate( self.tsa_cert)), simple_cms_attribute('message_digest', message_digest_value), ]) priv_key = serialization.load_der_private_key(self.tsa_key.dump(), password=None) if not isinstance(priv_key, RSAPrivateKey): raise NotImplementedError("Dummy timestamper is RSA-only.") signature = priv_key.sign( signed_attrs.dump(), PKCS1v15(), get_pyca_cryptography_hash(md_algorithm.upper())) 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': algos.SignedDigestAlgorithm({'algorithm': 'rsassa_pkcs1v15'}), '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})