wbond / oscrypto

Compiler-free Python crypto library backed by the OS, supporting CPython and PyPy
MIT License
318 stars 71 forks source link

test_load_rsa_pss_cert fails #58

Closed nmeum closed 2 years ago

nmeum commented 2 years ago

Hi,

While upgrading the Alpine Linux oscrypto package to 1.3.0 I noticed the following test failure:

======================================================================
ERROR: test_load_rsa_pss_cert (tests.test_asymmetric.AsymmetricTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/soeren/src/aports/community/py3-oscrypto/src/oscrypto-1.3.0/tests/test_asymmetric.py", line 143, in test_load_rsa_pss_cert
    self.assertEqual(2048, cert.bit_size)
  File "/home/soeren/src/aports/community/py3-oscrypto/src/oscrypto-1.3.0/oscrypto/_asymmetric.py", line 216, in bit_size
    return self.public_key.bit_size
  File "/home/soeren/src/aports/community/py3-oscrypto/src/oscrypto-1.3.0/oscrypto/_asymmetric.py", line 175, in bit_size
    return self.asn1.bit_size
  File "/usr/lib/python3.10/site-packages/asn1crypto/keys.py", line 1225, in bit_size
    self._bit_size = int(math.ceil(math.log(prime, 2)))
UnboundLocalError: local variable 'prime' referenced before assignment

Looking at the tests, the problem seems to be this test case:

https://github.com/wbond/oscrypto/blob/41c21afdc5f04afcfa47ee2b65455fe31e15d6f5/tests/test_asymmetric.py#L140-L143

This seems to create a key with algorithm rsassa_pss, however, the bit_size() implementation from /usr/lib/python3.10/site-packages/asn1crypto/keys.py does not seem to support this algorithm:

    def bit_size(self):
        """
        :return:
            The bit size of the public key, as an integer
        """

        if self._bit_size is None:
            if self.algorithm == 'ec':
                self._bit_size = int(((len(self['public_key'].native) - 1) / 2) * 8)
            else:
                if self.algorithm == 'rsa':
                    prime = self['public_key'].parsed['modulus'].native
                elif self.algorithm == 'dsa':
                    prime = self['algorithm']['parameters']['p'].native
                self._bit_size = int(math.ceil(math.log(prime, 2)))
                modulus = self._bit_size % 8
                if modulus != 0:
                    self._bit_size += 8 - modulus

        return self._bit_size

That is, prime is unset if the algorithm is neither rsa nor dsa. As such, I would assume this to be a bug in oscrypto.

rathann commented 2 years ago

asn1crypto 1.5.1 does support rsassa_pss:

        if self._bit_size is None:
            if self.algorithm == 'rsa' or self.algorithm == 'rsassa_pss':
                prime = self['private_key'].parsed['modulus'].native
            elif self.algorithm == 'dsa':

You need to update asn1crypto in your build environment.

nmeum commented 2 years ago

Indeed, my bad. Sorry for the noise.