Beispiel #1
0
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)
Beispiel #2
0
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
Beispiel #3
0
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