pythonshellssltrusted-timestamp

python rfc3161 verification failed but openssl verification is ok


I am trying to get my content timestamped so I know when it was changed. First I used a shell script but I want to implement it in my python program. the shell script works fine for now but I can't get the python version to work for me. This is the working shell version

in_file='test_content'
out_file="${in_file}.tsr"
ts_server='http://time.certum.pl/'
openssl ts -query -data "$in_file" -sha1 -cert | curl -o "$out_file" -sSH 'Content-Type: application/timestamp-query' --data-binary @- "$ts_server"
openssl ts -verify -data "$in_file" -in "$out_file" -CAfile "/usr/lib/ssl/certs/Certum_Trusted_Network_CA.pem"
openssl ts -reply -in "$out_file" -text

I tried to mimic this with rfc3161 package but the verification is not going as expected. This is the python code

import rfc3161

cert = file('/usr/lib/ssl/certs/Certum_Trusted_Network_CA.pem').read()
rt = rfc3161.RemoteTimestamper('http://time.certum.pl/', certificate=cert)
data_to_sign = file('test_content').read()
print rt.timestamp(data=data_to_sign)
>>> (False, 'Bad signature')

I don't know what is wrong since both scripts should do the same thing. Can somebody give me a clue on what is wrong with the python version?


Solution

  • The problem lies in the library rfc3161 that I used. It seems like the author does not include check for TSA authority certificate so I had to make a change to the library.

    The changed code is in api.py in check_timestamp function. You have to change the code block for certificate loading with this one:

    EDIT: The Certificate from the response should be validated against some certificate store. If you cannot validate it u should raise an Exception

    if certificate != "":
        try:
            certificate = X509.load_cert_der_string(encoder.encode(signed_data['certificates'][0][0]))
            # YOU SHOULD VALIDATE THE CERTIFICATE AGAINST SOME CERTIFICATE STORE !!!! 
            if not validate_certificate(certificate): #NOTE: I am not ready with this function.
                raise TypeError('The TSA returned certificate should be valid one')
        except:
            raise AttributeError("missing certificate")
    else:
        try:
            certificate = X509.load_cert_string(certificate)
        except:
            certificate = X509.load_cert_der_string(certificate)
    

    EDIT2: for validation you can use the code described here:

    Now the verification is working as expected.