FreeOpcUa/opcua-asyncio

generate_private_key produces key that can't be loaded with load_private_key

rth opened this issue · 2 comments

rth commented

I run into a case where, a private key generated with generate_private_key cannot be loaded with load_private_key.

The minimal example is,

from asyncua.crypto.uacrypto import load_private_key
from asyncua.crypto.cert_gen import generate_private_key, dump_private_key_as_pem
from pathlib import Path


async def main():
    key_file = Path("/tmp/cert.key")
    key = generate_private_key()
    key_file.write_bytes(dump_private_key_as_pem(key))

    key2 = await load_private_key(key_file)    
	

if __name__ == '__main__':
    import asyncio
    asyncio.run(main())

which produces the exception below,

Traceback (most recent call last):
  File "check_private_key.py", line 16, in <module>
    asyncio.run(main())
  File "lib/python3.11/asyncio/runners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "lib/python3.11/asyncio/runners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "lib/python3.11/asyncio/base_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "check_private_key.py", line 11, in main
    key2 = await load_private_key(key_file)    
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "lib/python3.11/site-packages/asyncua/crypto/uacrypto.py", line 80, in load_private_key
    return serialization.load_der_private_key(content, password=password, backend=default_backend())
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "lib/python3.11/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 494, in _handle_key_loading_error
    raise ValueError(
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).', [<OpenSSLError(code=109052072, lib=13, reason=168, reason_text=wrong tag)>, <OpenSSLError(code=109576458, lib=13, reason=524554, reason_text=nested asn1 error)>])

maybe due the cryptography / openssl combination. This was obtained with

Version

Python: 3.11
opcua-asyncio Version 1.0.6 (but I checked that none of the used function had relevant changes since)
cryptography: 42.0.8
pyopenssl 24.0.0
MacOS with conda environment where OpenSSL 3.2.1 was installed with conda

I'll try different versions in a follow up comment

rth commented

Trying to reinstall from scratch in a new Python 3.12 env with latest versions of dependencies

asyncua           1.1.5
cryptography      43.0.1
pycparser         2.22
pyOpenSSL         24.2.1
OpenSSL            3.3.2

still same error. For context I hit this while trying to use setup_self_signed_certificate

Edit: can also reproduce it in CI #1723

rth commented

OK, got it the file name extension needs to be .pem otherwise load_private_key will use load_der_private_key which is not the right loader.