trbs / rfc3161ng

A simple client library for cryptographic timestamping service implementing the protocol from RFC3161. Based on python-rfc3161 with some additional fixes.
Other
42 stars 19 forks source link

PyAsn1Error: Attempted "__index__" operation on ASN.1 schema object #24

Open paris-ci opened 1 month ago

paris-ci commented 1 month ago

When using rfc3161ng with some TSAs, the timestamping process fails with the following error :

In [1]: with open("freetsa.crt", "rb") as f:
   ...:     certificate = f.read()
   ...:

In [2]: import rfc3161ng
   ...:

In [3]: rt = rfc3161ng.RemoteTimestamper("https://freetsa.org/tsr", certificate=certificate)

In [4]: tst = rt.timestamp(data=b"hello")

In [5]: with open("sectigo.crt", "rb") as f:
   ...:     certificate = f.read()
   ...:

In [6]: rt = rfc3161ng.RemoteTimestamper("http://timestamp.sectigo.com", certificate=certificate)

In [7]: tst = rt.timestamp(data=b"hello")
---------------------------------------------------------------------------
PyAsn1Error                               Traceback (most recent call last)
Cell In[7], line 1
----> 1 tst = rt.timestamp(data=b"hello")

File ~/.pyenv/versions/3.12.5/lib/python3.12/site-packages/rfc3161ng/api.py:233, in RemoteTimestamper.timestamp(self, data, digest, include_tsa_certificate, nonce, tsa_policy_id)
    232 def timestamp(self, data=None, digest=None, include_tsa_certificate=None, nonce=None, tsa_policy_id=None):
--> 233     return self(
    234         data=data,
    235         digest=digest,
    236         include_tsa_certificate=include_tsa_certificate,
    237         nonce=nonce,
    238         tsa_policy_id=tsa_policy_id,
    239     )

File ~/.pyenv/versions/3.12.5/lib/python3.12/site-packages/rfc3161ng/api.py:274, in RemoteTimestamper.__call__(self, data, digest, include_tsa_certificate, nonce, return_tsr, tsa_policy_id)
    272     raise TimestampingError('Unable to send the request to %r' % self.url, exc)
    273 tsr = decode_timestamp_response(response.content)
--> 274 self.check_response(tsr, digest, nonce=nonce)
    275 if return_tsr:
    276     return tsr

File ~/.pyenv/versions/3.12.5/lib/python3.12/site-packages/rfc3161ng/api.py:219, in RemoteTimestamper.check_response(self, response, digest, nonce)
    217 tst = response.time_stamp_token
    218 if self.certificate:
--> 219     return self.check(tst, digest=digest, nonce=nonce)
    220 return tst

File ~/.pyenv/versions/3.12.5/lib/python3.12/site-packages/rfc3161ng/api.py:223, in RemoteTimestamper.check(self, tst, data, digest, nonce)
    222 def check(self, tst, data=None, digest=None, nonce=None):
--> 223     return check_timestamp(
    224         tst,
    225         digest=digest,
    226         data=data,
    227         nonce=nonce,
    228         certificate=self.certificate,
    229         hashname=self.hashname,
    230     )

File ~/.pyenv/versions/3.12.5/lib/python3.12/site-packages/rfc3161ng/api.py:146, in check_timestamp(tst, certificate, data, digest, hashname, nonce)

    144     raise ValueError('nonce is different or missing')
    145 # check message imprint with respect to locally computed digest
--> 146 message_imprint = tst.tst_info.message_imprint
    147 if message_imprint.hash_algorithm[0] != get_hash_oid(hashname) or bytes(message_imprint.hashed_message) != digest:
    148     raise ValueError('Message imprint mismatch')

File ~/.pyenv/versions/3.12.5/lib/python3.12/site-packages/rfc3161ng/types.py:111, in TimeStampToken.tst_info(self)
    109 @property
    110 def tst_info(self):
--> 111     x, substrate = decoder.decode(bytes(self.content['contentInfo']['content']))
    112     if substrate:
    113         raise ValueError('Incomplete decoding')

File ~/.pyenv/versions/3.12.5/lib/python3.12/site-packages/pyasn1/type/univ.py:912, in OctetString.__bytes__(self)
    911 def __bytes__(self):
--> 912     return bytes(self._value)

File ~/.pyenv/versions/3.12.5/lib/python3.12/site-packages/pyasn1/type/base.py:213, in NoValue.__new__.<locals>.getPlug.<locals>.plug(self, *args, **kw)
    212 def plug(self, *args, **kw):
--> 213     raise error.PyAsn1Error('Attempted "%s" operation on ASN.1 schema object' % name)

PyAsn1Error: Attempted "__index__" operation on ASN.1 schema object

As you can see, it works with freetsa just fine, but sectigo errors out.

I've attached the two certificates to the issue in the following zip file Archive.zip -- can't upload .crt directly to github.