0

I am getting ValueError("Could not deserialize key data.") if I use load_pem_private_key from from cryptography.hazmat.primitives.serialization

To add more context:

My key starts with

-----BEGIN OPENSSH PRIVATE KEY-----

The code segment that raises this Error

key = serialization.load_pem_private_key(data=private_key.encode(),
                                         password=None,
                                         backend=default_backend())

The traceback of the error shows

backend=default_backend()) -> return backend.load_pem_private_key(data, password) in load_pem_private_key -> password, in load_pem_private_key -> self._handle_key_loading_error() in _load_key

Ghasem
  • 14,455
  • 21
  • 138
  • 171
reddy nishanth
  • 396
  • 6
  • 11

2 Answers2

3

As of cryptography version 3.0 (released 2020-07-20), you can now use the load_ssh_private_key() function to load SSH private keys that are stored in the OPENSSH PRIVATE KEY PEM format:

$ ssh-keygen -t ed25519 -f demo_keypair -N 'example-passphrase' -C ''
$ python -c '
from cryptography.hazmat.primitives.serialization import load_ssh_private_key
from hashlib import sha1
key = load_ssh_private_key(open("demo_keypair", "rb").read(), b"example-passphrase")
print(sha1(key.sign(b"demo data")).hexdigest())
'
df551fcad0a0e288f0f92ca9e4876eb57a483c27

Note that to load a passphrase protected key you must have the bcrypt module installed (version 3.1.5 or newer); the documentation unfortunately doesn't make this explicit, but the error message you get if bcrypt is not installed is reasonably clear:

cryptography.exceptions.UnsupportedAlgorithm: Need bcrypt module

You can use the ssh extra to pull in bcrypt as a dependency:

pip install cryptography[ssh]
PiQuer
  • 2,383
  • 25
  • 29
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
1

pyca/cryptography mostly uses OpenSSL, and for private key supports mostly the formats OpenSSL supports which does not include OpenSSH's 'new' format. It does however add the OpenSSH public key format, so it might not be absurd to ask them about adding OpenSSH private. In the interim ...

Given you have OpenSSH, you can use ssh-keygen to convert the OpenSSH 'new' format back to OpenSSH's 'old' format which is OpenSSL's 'traditional' or 'legacy' format, by claiming you want to change the password -- even if you make the new password the same as the old password, or since you apparently want an unencrypted file, make the new password empty just as did the old password:

# OpenSSH 7.8 up 
ssh-keygen -f keyfile -p -m pem 
# below 7.8 
ssh-keygen -f keyfile -p # NOT -o 

Or if you have PuTTY 0.69 up, puttygen can also do this, although the UI varies between Windows and Unix.

Dupes:
SSH key generated by ssh-keygen is not recognized by Paramiko: "not a valid RSA private key file" (Paramiko is SSH in Python)
"Invalid privatekey" when using JSch (Java, but same issue)

dave_thompson_085
  • 34,712
  • 6
  • 50
  • 70