How to use RSA private key with PyCrypto?

I generate a key with OpenSSL by providing a password from stdin:

openssl genpkey -algorithm RSA -out private-key.pem -outform PEM -pass stdin -des3 -pkeyopt rsa_keygen_bits:4096 

The key is as follows:

 -----BEGIN ENCRYPTED PRIVATE KEY----- XXX... -----END ENCRYPTED PRIVATE KEY----- 

My Python code looks like this:

 from Crypto.PublicKey import RSA # ... f = open('private-key.pem', 'r') r = RSA.importKey(f.read(), passphrase='some-pass') f.close() 

but I get an exception:

  File "/usr/lib/python2.7/dist-packages/Crypto/PublicKey/RSA.py", line 665, in importKey return self._importKeyDER(der) File "/usr/lib/python2.7/dist-packages/Crypto/PublicKey/RSA.py", line 588, in _importKeyDER raise ValueError("RSA key format is not supported") ValueError: RSA key format is not supported 

What's wrong?

Can I generate an encrypted RSA key, store it in a file and use it later with PyCrypto? Can this be done using OpenSSL? What formats are supported?

Importing a public key works fine, but it is not encrypted.

+6
source share
2 answers

Hypothesis No. 1

Looking at the source code, I think I solved the secret. The way the import of password-encrypted PEM keys works is that PEM is decrypted to DER and then the importKeyDER function is called. If the password provided is incorrect, the format of the generated DER view will also not be correct, and you will get the exception that you provided. To confirm this, I conducted two quick tests below:

 >>> from Crypto.PublicKey import RSA >>> f = open('<some-path>/private-key.pem','r') >>> r=RSA.importKey(f.read(),passphrase='foo') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/python2.7/dist-packages/Crypto/PublicKey/RSA.py", line 665, in importKey return self._importKeyDER(der) File "/usr/local/lib/python2.7/dist-packages/Crypto/PublicKey/RSA.py", line 588, in _importKeyDER raise ValueError("RSA key format is not supported") ValueError: RSA key format is not supported >>> f = open('<some-path>/private-key.pem','r') >>> r=RSA.importKey(f.read(),passphrase='<valid-pass-phrase>') >>> r <_RSAobj @0xb7237b2c n(4096),e,d,p,q,u,private> 

After receiving PEM from the author, I realized that hypothesis number 1 is not valid for his case. I still want to keep it here as one of the possible reasons for the import failure, so other users know.

Hypothesis No. 2 is the case of the author.

RSA.py looks in the PEM file for the following to determine which encryption has been applied to the PEM:

  Proc-Type: 4,ENCRYPTED 

When a key is generated using the command "openssl genrsa ...", this line is present in PEM in a clear form, but when using "opensl genpkey ..." there is no "Proc-Type".

RSA.py does not even try to decrypt PEM if "Proc-Type" is not found:

  # The encrypted PEM format if lines[1].startswith(b('Proc-Type:4,ENCRYPTED')): DEK = lines[2].split(b(':')) .... 

So, my conclusion this time is that the keys generated by "openssl genpkey" are not supported by PyCrypto v 2.6.1.

Important update

It works in PyCrypto latest version 2.7a1. You can download it here: http://ftp.dlitz.net/pub/dlitz/crypto/pycrypto/pycrypto-2.7a1.tar.gz

 >>> f = open('key.pem','r') >>> r = RSA.importKey(f.read(), passphrase='123456') >>> r <_RSAobj @0xb6f342ec n(2048),e,d,p,q,u,private> 
+4
source

A quick update for those who seek to solve this problem without installing an experimental version of the long-forgotten PyCrypto. The library can be safely replaced with pycryptodome ( https://github.com/Legrandin/pycryptodome ) - it can provide a replacement replacement for pycrypto, and it can also be used as an alternative library (pycryptodomex).

+2
source

Source: https://habr.com/ru/post/969810/


All Articles