Skip to content

2.5.0: pytest is failing in tests/test_algorithms.py::TestAlgorithms::test_ec_to_jwk_with_invalid_curve unit #802

@kloczek

Description

@kloczek

I'm packaging your module as an rpm package so I'm using the typical PEP517 based build, install and test cycle used on building packages from non-root account.

  • python3 -sBm build -w --no-isolation
  • because I'm calling build with --no-isolation I'm using during all processes only locally installed modules
  • install .whl file in </install/prefix>
  • run pytest with PYTHONPATH pointing to sitearch and sitelib inside </install/prefix>

Here is pytest output:

Details
+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-jwt-2.5.0-2.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-jwt-2.5.0-2.fc35.x86_64/usr/lib/python3.8/site-packages
+ /usr/bin/pytest -ra
=========================================================================== test session starts ============================================================================
platform linux -- Python 3.8.13, pytest-7.1.3, pluggy-1.0.0
rootdir: /home/tkloczko/rpmbuild/BUILD/pyjwt-2.5.0, configfile: tox.ini, testpaths: tests
collected 241 items

tests/test_advisory.py .                                                                                                                                             [  0%]
tests/test_algorithms.py .............................F.........................................                                                                     [ 29%]
tests/test_api_jwk.py ..................                                                                                                                             [ 37%]
tests/test_api_jws.py ..................................s..................................                                                                          [ 65%]
tests/test_api_jwt.py .....................................................                                                                                          [ 87%]
tests/test_exceptions.py .                                                                                                                                           [ 88%]
tests/test_jwks_client.py ...............                                                                                                                            [ 94%]
tests/test_jwt.py .                                                                                                                                                  [ 95%]
tests/test_utils.py .....x......                                                                                                                                     [100%]

================================================================================= FAILURES =================================================================================
_____________________________________________________________ TestAlgorithms.test_ec_to_jwk_with_invalid_curve _____________________________________________________________

self = <jwt.algorithms.ECAlgorithm object at 0x7fcf475df910>
key = b'-----BEGIN PRIVATE KEY-----\nMG8CAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEEVTBTAgEBBBiON6kYcPu8ZUDRTu8W\neXJ2FmX7e9yq0hahNAMyAARHecLjkXWDUJfZ4wiFH61JpmonCYH1GpinVlqw68Sf\nwtDHg2F6SifQEFC6VKj1ZXw=\n-----END PRIVATE KEY-----\n'

    def prepare_key(self, key):
        if isinstance(key, (EllipticCurvePrivateKey, EllipticCurvePublicKey)):
            return key

        if not isinstance(key, (bytes, str)):
            raise TypeError("Expecting a PEM-formatted key.")

        key = force_bytes(key)

        # Attempt to load key. We don't know if it's
        # a Signing Key or a Verifying Key, so we try
        # the Verifying Key first.
        try:
            if key.startswith(b"ecdsa-sha2-"):
                key = load_ssh_public_key(key)
            else:
>               key = load_pem_public_key(key)

jwt/algorithms.py:411:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

data = b'-----BEGIN PRIVATE KEY-----\nMG8CAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEEVTBTAgEBBBiON6kYcPu8ZUDRTu8W\neXJ2FmX7e9yq0hahNAMyAARHecLjkXWDUJfZ4wiFH61JpmonCYH1GpinVlqw68Sf\nwtDHg2F6SifQEFC6VKj1ZXw=\n-----END PRIVATE KEY-----\n'
backend = None

    def load_pem_public_key(
        data: bytes, backend: typing.Any = None
    ) -> PUBLIC_KEY_TYPES:
        from cryptography.hazmat.backends.openssl.backend import backend as ossl

>       return ossl.load_pem_public_key(data)

/usr/lib64/python3.8/site-packages/cryptography/hazmat/primitives/serialization/base.py:30:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <OpenSSLBackend(version: OpenSSL 3.0.5 5 Jul 2022, FIPS: False)>
data = b'-----BEGIN PRIVATE KEY-----\nMG8CAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEEVTBTAgEBBBiON6kYcPu8ZUDRTu8W\neXJ2FmX7e9yq0hahNAMyAARHecLjkXWDUJfZ4wiFH61JpmonCYH1GpinVlqw68Sf\nwtDHg2F6SifQEFC6VKj1ZXw=\n-----END PRIVATE KEY-----\n'

    def load_pem_public_key(self, data):
        mem_bio = self._bytes_to_bio(data)
        evp_pkey = self._lib.PEM_read_bio_PUBKEY(
            mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL
        )
        if evp_pkey != self._ffi.NULL:
            evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free)
            return self._evp_pkey_to_public_key(evp_pkey)
        else:
            # It's not a (RSA/DSA/ECDSA) subjectPublicKeyInfo, but we still
            # need to check to see if it is a pure PKCS1 RSA public key (not
            # embedded in a subjectPublicKeyInfo)
            self._consume_errors()
            res = self._lib.BIO_reset(mem_bio.bio)
            self.openssl_assert(res == 1)
            rsa_cdata = self._lib.PEM_read_bio_RSAPublicKey(
                mem_bio.bio, self._ffi.NULL, self._ffi.NULL, self._ffi.NULL
            )
            if rsa_cdata != self._ffi.NULL:
                rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free)
                evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata)
                return _RSAPublicKey(self, rsa_cdata, evp_pkey)
            else:
>               self._handle_key_loading_error()

/usr/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/backend.py:853:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <OpenSSLBackend(version: OpenSSL 3.0.5 5 Jul 2022, FIPS: False)>

    def _handle_key_loading_error(self):
        errors = self._consume_errors()

        if not errors:
            raise ValueError(
                "Could not deserialize key data. The data may be in an "
                "incorrect format or it may be encrypted with an unsupported "
                "algorithm."
            )

        elif (
            errors[0]._lib_reason_match(
                self._lib.ERR_LIB_EVP, self._lib.EVP_R_BAD_DECRYPT
            )
            or errors[0]._lib_reason_match(
                self._lib.ERR_LIB_PKCS12,
                self._lib.PKCS12_R_PKCS12_CIPHERFINAL_ERROR,
            )
            or (
                self._lib.Cryptography_HAS_PROVIDERS
                and errors[0]._lib_reason_match(
                    self._lib.ERR_LIB_PROV,
                    self._lib.PROV_R_BAD_DECRYPT,
                )
            )
        ):
            raise ValueError("Bad decrypt. Incorrect password?")

        elif any(
            error._lib_reason_match(
                self._lib.ERR_LIB_EVP,
                self._lib.EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM,
            )
            for error in errors
        ):
            raise ValueError("Unsupported public key algorithm.")

        else:
            errors = binding._errors_with_text(errors)
>           raise ValueError(
                "Could not deserialize key data. The data may be in an "
                "incorrect format, it may be encrypted with an unsupported "
                "algorithm, or it may be an unsupported key type (e.g. EC "
                "curves with explicit parameters).",
                errors,
            )
E           ValueError: ('Could not deserialize key data. The data may be in an incorrect format, it may be encrypted with an unsupported algorithm, or it may be an unsupported key type (e.g. EC curves with explicit parameters).', [_OpenSSLErrorWithText(code=75497580, lib=9, reason=108, reason_text=b'error:0480006C:PEM routines::no start line')])

/usr/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/backend.py:1129: ValueError

During handling of the above exception, another exception occurred:

self = <tests.test_algorithms.TestAlgorithms object at 0x7fcf479a21c0>

    @crypto_required
    def test_ec_to_jwk_with_invalid_curve(self):
        algo = ECAlgorithm(ECAlgorithm.SHA256)

        with open(key_path("testkey_ec_secp192r1.priv")) as keyfile:
>           priv_key = algo.prepare_key(keyfile.read())

tests/test_algorithms.py:331:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
jwt/algorithms.py:413: in prepare_key
    key = load_pem_private_key(key, password=None)
/usr/lib64/python3.8/site-packages/cryptography/hazmat/primitives/serialization/base.py:22: in load_pem_private_key
    return ossl.load_pem_private_key(data, password)
/usr/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/backend.py:823: in load_pem_private_key
    return self._load_key(
/usr/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/backend.py:1070: in _load_key
    self._handle_key_loading_error()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <OpenSSLBackend(version: OpenSSL 3.0.5 5 Jul 2022, FIPS: False)>

    def _handle_key_loading_error(self):
        errors = self._consume_errors()

        if not errors:
            raise ValueError(
                "Could not deserialize key data. The data may be in an "
                "incorrect format or it may be encrypted with an unsupported "
                "algorithm."
            )

        elif (
            errors[0]._lib_reason_match(
                self._lib.ERR_LIB_EVP, self._lib.EVP_R_BAD_DECRYPT
            )
            or errors[0]._lib_reason_match(
                self._lib.ERR_LIB_PKCS12,
                self._lib.PKCS12_R_PKCS12_CIPHERFINAL_ERROR,
            )
            or (
                self._lib.Cryptography_HAS_PROVIDERS
                and errors[0]._lib_reason_match(
                    self._lib.ERR_LIB_PROV,
                    self._lib.PROV_R_BAD_DECRYPT,
                )
            )
        ):
            raise ValueError("Bad decrypt. Incorrect password?")

        elif any(
            error._lib_reason_match(
                self._lib.ERR_LIB_EVP,
                self._lib.EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM,
            )
            for error in errors
        ):
            raise ValueError("Unsupported public key algorithm.")

        else:
            errors = binding._errors_with_text(errors)
>           raise ValueError(
                "Could not deserialize key data. The data may be in an "
                "incorrect format, it may be encrypted with an unsupported "
                "algorithm, or it may be an unsupported key type (e.g. EC "
                "curves with explicit parameters).",
                errors,
            )
E           ValueError: ('Could not deserialize key data. The data may be in an incorrect format, it may be encrypted with an unsupported algorithm, or it may be an unsupported key type (e.g. EC curves with explicit parameters).', [_OpenSSLErrorWithText(code=503841036, lib=60, reason=524556, reason_text=b'error:1E08010C:DECODER routines::unsupported'), _OpenSSLErrorWithText(code=134217857, lib=16, reason=129, reason_text=b'error:08000081:elliptic curve routines::unknown group')])

/usr/lib64/python3.8/site-packages/cryptography/hazmat/backends/openssl/backend.py:1129: ValueError
========================================================================= short test summary info ==========================================================================
SKIPPED [1] tests/test_api_jws.py:388: Requires cryptography library not installed
XFAIL tests/test_utils.py::test_to_base64url_uint[-1-]
FAILED tests/test_algorithms.py::TestAlgorithms::test_ec_to_jwk_with_invalid_curve - ValueError: ('Could not deserialize key data. The data may be in an incorrect format...
=========================================================== 1 failed, 238 passed, 1 skipped, 1 xfailed in 5.73s ============================================================

Here is list of installed modules in build env

Details
Package                       Version
----------------------------- -----------------
alabaster                     0.7.12
appdirs                       1.4.4
attrs                         22.1.0
Babel                         2.10.2
Brlapi                        0.8.3
build                         0.8.0
cffi                          1.15.1
charset-normalizer            2.1.0
codespell                     2.2.1
cryptography                  36.0.2
cssselect                     1.1.0
cycler                        0.11.0
distro                        1.7.0
docutils                      0.18.1
extras                        1.0.0
fixtures                      4.0.0
fonttools                     4.37.1
gpg                           1.17.1-unknown
idna                          3.3
imagesize                     1.4.1
importlib-metadata            4.12.0
iniconfig                     1.1.1
Jinja2                        3.1.1
kiwisolver                    1.4.4
libcomps                      0.1.19
louis                         3.23.0
lxml                          4.9.1
MarkupSafe                    2.1.1
matplotlib                    3.5.3
numpy                         1.23.1
olefile                       0.46
packaging                     21.3
pbr                           5.9.0
pep517                        0.12.0
Pillow                        9.2.0
pip                           22.2.2
pluggy                        1.0.0
ply                           3.11
py                            1.11.0
pycparser                     2.21
Pygments                      2.13.0
PyGObject                     3.42.2
pyparsing                     3.0.9
pytest                        7.1.3
python-dateutil               2.8.2
pytz                          2022.1
requests                      2.28.1
rpm                           4.17.0
scour                         0.38.2
setuptools                    65.3.0
six                           1.16.0
snowballstemmer               2.2.0
Sphinx                        5.1.1
sphinx-rtd-theme              1.0.0
sphinxcontrib-applehelp       1.0.2.dev20220730
sphinxcontrib-devhelp         1.0.2.dev20220730
sphinxcontrib-htmlhelp        2.0.0
sphinxcontrib-jsmath          1.0.1.dev20220730
sphinxcontrib-qthelp          1.0.3.dev20220730
sphinxcontrib-serializinghtml 1.1.5
testtools                     2.5.0
tomli                         2.0.1
urllib3                       1.26.12
wheel                         0.37.1
zipp                          3.8.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions