2

I am trying to load a passphrase-protected private SSH key from a file using the cryptography Python module. However, I'm not exactly sure how to proceed. The following yields a Crypto.Util.Padding.PaddingError: Padding is incorrect. error.

def importPrivateKey(private_key,passphrase):
  """
  Imports the private key in an RSA object and generates the hash.
  """

  # -- Test with pgcrypto (now deprecated) -- WORKS
  with open(private_key, 'r') as private_key_file:
    key = RSA.importKey(private_key_file.read(),passphrase=passphrase)

  print(key)

  # -- Test with cryptography (active) -- FAILS
  with open(private_key,'r') as private_key_file:
    key = load_pem_private_key(private_key_file.read(),password=passphrase,backend=RSABackend())

  print(key)
  SecureString.clearmem(passphrase)

  return key

You can see from the snippet that I have working solution using the pycrypto module, but this module has not been updated in 5 years now. The code that uses cryptography fails with the aforementioned error.

I know there is load_public_ssh_key deserialization function, but this seems to operate on decrypted keys, hence my choice of load_pem_private_key.

Is it possible to load both private/public keys with the cryptography module?

2
  • This is indeed an interesting Q/A pair, but IMHO it would be more on topic on SO. Commented Jan 25, 2019 at 15:12
  • This question is now too old to migrate. If you want to delete it, you would have to delete the answer first.
    – schroeder
    Commented Jun 4, 2020 at 7:15

1 Answer 1

2

Like any beginner, I made this more complicated that it needed to be, and didn't read the documentation properly.

The key must be read as bytes ('rb'), and the passphrase must also be bytes-like, as per the documentation.

import SecretString
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.serialization import load_ssh_public_key, load_pem_private_key
from cryptography.hazmat.primitives.serialization import Encoding
from cryptography.hazmat.primitives.serialization import PublicFormat

def importPrivateKey(private_key,passphrase):
  """
  Imports the private key in an RSA object and generates the hash.
  """
  with open(private_key,'rb') as private_key_file:
    key = load_pem_private_key(private_key_file.read(),
                               password=passphrase.encode(),
                               backend=default_backend())

  public_key = key.public_key()

  print(public_key.public_bytes(Encoding.OpenSSH,PublicFormat.OpenSSH))
  SecureString.clearmem(passphrase)

  return key

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .