def get_timestamp(tst, naive=True): try: if not isinstance(tst, rfc3161ng.TimeStampToken): tst, substrate = decoder.decode(tst, asn1Spec=rfc3161ng.TimeStampToken()) if substrate: raise ValueError("extra data after tst") tstinfo = tst.getComponentByName('content').getComponentByPosition(2).getComponentByPosition(1) tstinfo, substrate = decoder.decode(tstinfo, asn1Spec=univ.OctetString()) if substrate: raise ValueError("extra data after tst") tstinfo, substrate = decoder.decode(tstinfo, asn1Spec=rfc3161ng.TSTInfo()) if substrate: raise ValueError("extra data after tst") genTime = tstinfo.getComponentByName('genTime') return generalizedtime_to_utc_datetime(str(genTime), naive) except PyAsn1Error as exc: raise ValueError('not a valid TimeStampToken', exc)
def add_tsa(text, hash_data): url = 'http://time.certum.pl' certificate = open(CERTIFICATE, 'rb').read() rt = rfc3161ng.RemoteTimestamper(url, certificate=certificate, include_tsa_certificate=True) write_file(CERTIFICATE_PATH, 'certificate ' + text + '.crt', rt.certificate) tst = rt.timestamp(data=hash_data) tsq = rfc3161ng.make_timestamp_request(data=hash_data) binary_request = rfc3161ng.encode_timestamp_request(tsq) headers = {'Content-Type': 'application/timestamp-query'} response = requests.post( url, data=binary_request, timeout=10, headers=headers, ) tsr = rfc3161ng.decode_timestamp_response(response.content) tst1, substrate = decoder.decode(tst, asn1Spec=rfc3161ng.TimeStampToken()) signed_data = tst1.content signer_info = signed_data['signerInfos'][0] tsa_signature = bytes(signer_info['encryptedDigest']).hex() write_object_file(RESPONSE_PATH, 'response ' + text + '.tsr', tsr) # with open("Output.txt", "w") as text_file: # text_file.write("%s" % tsr) tst = tsr.time_stamp_token tst1 = tst.content tst2 = tst.tst_info tss = tsr.status return tsa_signature
def check_timestamp(tst, certificate, data=None, digest=None, hashname=None, nonce=None): hashname = hashname or 'sha1' hashobj = hashlib.new(hashname) if digest is None: if not data: raise ValueError( "check_timestamp requires data or digest argument") hashobj.update(data) digest = hashobj.digest() if not isinstance(tst, rfc3161ng.TimeStampToken): tst, substrate = decoder.decode(tst, asn1Spec=rfc3161ng.TimeStampToken()) if substrate: raise ValueError("extra data after tst") signed_data = tst.content certificate = load_certificate(signed_data, certificate) if nonce is not None and int(tst.tst_info['nonce']) != int(nonce): raise ValueError('nonce is different or missing') # check message imprint with respect to locally computed digest message_imprint = tst.tst_info.message_imprint if message_imprint.hash_algorithm[0] != get_hash_oid(hashname) or bytes( message_imprint.hashed_message) != digest: raise ValueError('Message imprint mismatch') if not len(signed_data['signerInfos']): raise ValueError('No signature') # We validate only one signature signer_info = signed_data['signerInfos'][0] # check content type if tst.content['contentInfo']['contentType'] != rfc3161ng.id_ct_TSTInfo: raise ValueError("Signed content type is wrong: %s != %s" % (tst.content['contentInfo']['contentType'], rfc3161ng.id_ct_TSTInfo)) # check signed data digest content = bytes( decoder.decode(bytes(tst.content['contentInfo']['content']), asn1Spec=univ.OctetString())[0]) # if there is authenticated attributes, they must contain the message # digest and they are the signed data otherwise the content is the # signed data if len(signer_info['authenticatedAttributes']): authenticated_attributes = signer_info['authenticatedAttributes'] signer_digest_algorithm = signer_info['digestAlgorithm']['algorithm'] signer_hash_class = get_hash_class_from_oid(signer_digest_algorithm) signer_hash_name = get_hash_from_oid(signer_digest_algorithm) content_digest = signer_hash_class(content).digest() for authenticated_attribute in authenticated_attributes: if authenticated_attribute[0] == id_attribute_messageDigest: try: signed_digest = bytes( decoder.decode(bytes(authenticated_attribute[1][0]), asn1Spec=univ.OctetString())[0]) if signed_digest != content_digest: raise ValueError('Content digest != signed digest') s = univ.SetOf() for i, x in enumerate(authenticated_attributes): s.setComponentByPosition(i, x) signed_data = encoder.encode(s) break except PyAsn1Error: raise else: raise ValueError('No signed digest') else: signed_data = content # check signature signature = signer_info['encryptedDigest'] public_key = certificate.public_key() hash_family = getattr(hashes, signer_hash_name.upper()) public_key.verify( bytes(signature), signed_data, padding.PKCS1v15(), hash_family(), ) return True