pyca / cryptography

cryptography is a package designed to expose cryptographic primitives and recipes to Python developers.
https://cryptography.io
Other
6.71k stars 1.54k forks source link

load_pem_private_key fails with unexpected OpenSSL error depending on password #8563

Closed lukpueh closed 1 year ago

lukpueh commented 1 year ago

I have a test that creates an encrypted rsa key and then tries to load and decrypt it with load_pem_private_key, using an invalid password and asserting the error message "Bad decrypt. Incorrect password?".

Every now and then my test fails, because I get a different error message, i.e.: (pretty printed for better readability)

('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=109052027, lib=13, reason=123, reason_text=b'error:0680007B:asn1 encoding routines::header too long'),
  _OpenSSLErrorWithText(code=109052006, lib=13, reason=102, reason_text=b'error:06800066:asn1 encoding routines::bad object header'),
  _OpenSSLErrorWithText(code=109576458, lib=13, reason=524554, reason_text=b'error:0688010A:asn1 encoding routines::nested asn1 error'),
  _OpenSSLErrorWithText(code=109052027, lib=13, reason=123, reason_text=b'error:0680007B:asn1 encoding routines::header too long'),
  _OpenSSLErrorWithText(code=109052006, lib=13, reason=102, reason_text=b'error:06800066:asn1 encoding routines::bad object header'),
  _OpenSSLErrorWithText(code=109576458, lib=13, reason=524554, reason_text=b'error:0688010A:asn1 encoding routines::nested asn1 error')])

The key parses successfully when providing the correct password, and also raises the expected error when providing a different invalid password.

The following script can be used to reproduce the issue. Key is hard-coded, because the issue does not occur for every key created with the commented out snippet.

Reproducer

from cryptography.hazmat.primitives.serialization import load_pem_private_key

# # Create encrypted RSA PEM
# from cryptography.hazmat.backends import default_backend
# from cryptography.hazmat.primitives import serialization
# from cryptography.hazmat.primitives.asymmetric import rsa
#
# key = rsa.generate_private_key(
#     public_exponent=65537, key_size=3072, backend=default_backend()
# )
# encrypted_rsa_key = key.private_bytes(
#     encoding=serialization.Encoding.PEM,
#     format=serialization.PrivateFormat.TraditionalOpenSSL,
#     encryption_algorithm=serialization.BestAvailableEncryption(b"pw"),
# )

# Not every key triggers the unexpected error below, but this one does:
encrypted_rsa_key = b"-----BEGIN RSA PRIVATE KEY-----\nProc-Type: 4,ENCRYPTED\nDEK-Info: AES-256-CBC,6EF2C95AF143341584114A13ED0A8C06\n\n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\n-----END RSA PRIVATE KEY-----"

# Parse and decrypt successfully with valid password
load_pem_private_key(encrypted_rsa_key, b"pw")

# Fail with invalid password and expected error message: "Bad decrypt. Incorrect password?"
load_pem_private_key(encrypted_rsa_key, b"not pw")

# Fail with different invalid password and unexpected error message: "Could not deserialize key data..."
load_pem_private_key(encrypted_rsa_key, b"bad pw")

Environment

$ python --version
Python 3.10.9
$ pip list
Package      Version
------------ -------
cffi         1.15.1
cryptography 39.0.2
pip          23.0.1
pycparser    2.21
setuptools   67.4.0
wheel        0.38.4
alex commented 1 year ago

Unfortunately because PEM encryption is not authenticated, decryption can produce all sorts of invalid keys, we do not know if's because the password is wrong or because the decrypted contents was malformed.

On Wed, Mar 22, 2023 at 7:25 AM Lukas Pühringer @.***> wrote:

I have a test that creates an encrypted rsa key and then tries to load and decrypt it with load_pem_private_key, using an invalid password and asserting the error message "Bad decrypt. Incorrect password?".

Every now and then my test fails, because I get a different error message, i.e.: (pretty printed for better readability)

('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=109052027, lib=13, reason=123, reason_text=b'error:0680007B:asn1 encoding routines::header too long'), _OpenSSLErrorWithText(code=109052006, lib=13, reason=102, reason_text=b'error:06800066:asn1 encoding routines::bad object header'), _OpenSSLErrorWithText(code=109576458, lib=13, reason=524554, reason_text=b'error:0688010A:asn1 encoding routines::nested asn1 error'), _OpenSSLErrorWithText(code=109052027, lib=13, reason=123, reason_text=b'error:0680007B:asn1 encoding routines::header too long'), _OpenSSLErrorWithText(code=109052006, lib=13, reason=102, reason_text=b'error:06800066:asn1 encoding routines::bad object header'), _OpenSSLErrorWithText(code=109576458, lib=13, reason=524554, reason_text=b'error:0688010A:asn1 encoding routines::nested asn1 error')])

The key parses successfully when providing the correct password, and also raises the expected error when providing a different invalid password.

The following script can be used to reproduce the issue. Key is hard-coded, because the issue does not occur for every key created with the commented out snippet.

Reproducer

from cryptography.hazmat.primitives.serialization import load_pem_private_key

Create encrypted RSA PEM# from cryptography.hazmat.backends import default_backend# from cryptography.hazmat.primitives import serialization# from cryptography.hazmat.primitives.asymmetric import rsa## key = rsa.generate_private_key(# public_exponent=65537, key_size=3072, backend=default_backend()# )# encrypted_rsa_key = key.private_bytes(# encoding=serialization.Encoding.PEM,# format=serialization.PrivateFormat.TraditionalOpenSSL,# encryption_algorithm=serialization.BestAvailableEncryption(b"pw"),# )

Not every key triggers the unexpected error below, but this one does:encrypted_rsa_key = b"-----BEGIN RSA PRIVATE KEY-----\nProc-Type: 4,ENCRYPTED\nDEK-Info: AES-256-CBC,6EF2C95AF143341584114A13ED0A8C06\n\n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\n-----END RSA PRIVATE KEY-----"

Parse and decrypt successfully with valid passwordload_pem_private_key(encrypted_rsa_key, b"pw")

Fail with invalid password and expected error message: "Bad decrypt. Incorrect password?"load_pem_private_key(encrypted_rsa_key, b"not pw")

Fail with different invalid password and unexpected error message: "Could not deserialize key data..."load_pem_private_key(encrypted_rsa_key, b"bad pw")

Environment

$ python --version Python 3.10.9 $ pip list Package Version


cffi 1.15.1 cryptography 39.0.2 pip 23.0.1 pycparser 2.21 setuptools 67.4.0 wheel 0.38.4

— Reply to this email directly, view it on GitHub https://github.com/pyca/cryptography/issues/8563, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAAGBE6A6XM4QBQUK4UTYLW5LOS3ANCNFSM6AAAAAAWDVYEIQ . You are receiving this because you are subscribed to this thread.Message ID: @.***>

-- All that is necessary for evil to succeed is for good people to do nothing.

lukpueh commented 1 year ago

Makes sense. Thanks for the quick reply! Feel free to close the issue.

alex commented 1 year ago

Sorry we don't hvae a happier answer.