I am generating a key with OpenSSL, providing the password from stdin:
我正在使用OpenSSL生成一个密钥,提供来自stdin的密码:
openssl genpkey -algorithm RSA -out private-key.pem -outform PEM -pass stdin -des3 -pkeyopt rsa_keygen_bits:4096
The key then looks like:
关键是:
-----BEGIN ENCRYPTED PRIVATE KEY-----
XXX...
-----END ENCRYPTED PRIVATE KEY-----
My Python code looks like:
我的Python代码如下:
from Crypto.PublicKey import RSA
# ...
f = open('private-key.pem', 'r')
r = RSA.importKey(f.read(), passphrase='some-pass')
f.close()
but I am getting 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?
怎么了?
Is it possible to generate an encrypted RSA key, store it in a file and later use it with PyCrypto? Is it possible to do it with OpenSSL? What formats are supported?
是否可以生成一个加密的RSA密钥,将其存储在一个文件中,然后使用PyCrypto来使用它?有可能使用OpenSSL吗?支持哪些格式?
Importing the public key works fine, however it is not encrypted.
导入公钥可以正常工作,但是没有加密。
2 个解决方案
#1
4
Hypothesis #1
假设# 1
After looking to the source code, I think, I solved the mystery. The way how import works for PEM keys encrypted with a password is that the PEM gets decrypted to DER and after that importKeyDER function is called. If provided password is not correct, the format of generated DER representation will not be correct too and you would get an exception that you've provided. To confirm that, I ran two quick tests below:
在查找源代码之后,我想,我解决了这个谜。使用密码加密的PEM密钥的导入方法是,PEM将被解密到DER,然后调用importKeyDER函数。如果提供的密码不正确,生成的DER表示格式也不正确,您将得到一个您提供的异常。为了证实这一点,我在下面做了两个快速测试:
>>> 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 the PEM from the author, I've realized that Hypothesis #1 is not valid for his case. I still want to keep it here as one possible reason of import failure, so other users are aware.
在收到作者的PEM之后,我意识到假设1对他的案例是无效的。我仍然希望把它作为导入失败的一个可能原因,这样其他用户就知道了。
Hypothesis #2 - this is the author's case.
假设2 -这是作者的案例。
RSA.py looks for the following in PEM file to determine what kind of encryption was applied to PEM:
RSA。py在PEM文件中查找以下内容,以确定应用于PEM的加密类型:
Proc-Type: 4,ENCRYPTED
When key is generated using "openssl genrsa ..." command, this string is present in PEM in clear, however when "opensl genpkey ..." is used the "Proc-Type" is not present.
当使用“openssl genrsa…”命令生成密钥时,这个字符串在PEM中很清楚,但是当“opensl genpkey…”被使用时,“proc类型”就不存在了。
RSA.py doesn't even try to decrypt the PEM if the "Proc-Type" is not found:
RSA。如果没有找到“Proc-Type”,py甚至不会尝试解密PEM:
# The encrypted PEM format
if lines[1].startswith(b('Proc-Type:4,ENCRYPTED')):
DEK = lines[2].split(b(':'))
....
So, my conclusion at this time is that keys generated by "openssl genpkey" are not supported by PyCrypto v 2.6.1.
因此,我的结论是,由“openssl genpkey”生成的密钥不受PyCrypto v2.6.1的支持。
Important Update
重要更新
It does work in PyCrypto's latest version 2.7a1. You can download it from here: http://ftp.dlitz.net/pub/dlitz/crypto/pycrypto/pycrypto-2.7a1.tar.gz
它在PyCrypto的最新版本2.7a1中工作。您可以从这里下载: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>
#2
2
A quick update for those who seek to solve this problem without installing an experimental release of long-abandoned PyCrypto. The library can be safely replaced by pycryptodome (https://github.com/Legrandin/pycryptodome) - it can provide both a drop-in replacement for pycrypto, and it can be used as an alternative library as well (pycryptodomex).
对于那些试图解决这个问题的人来说,一个快速的更新,不需要安装一个实验性的释放已久的PyCrypto。这个库可以安全地被pycryptodome (https://github.com/Legrandin/pycryptodome)取代,它可以提供一个替代pycrypto的替代库,它也可以作为一个替代的库(pycryptodomex)。
#1
4
Hypothesis #1
假设# 1
After looking to the source code, I think, I solved the mystery. The way how import works for PEM keys encrypted with a password is that the PEM gets decrypted to DER and after that importKeyDER function is called. If provided password is not correct, the format of generated DER representation will not be correct too and you would get an exception that you've provided. To confirm that, I ran two quick tests below:
在查找源代码之后,我想,我解决了这个谜。使用密码加密的PEM密钥的导入方法是,PEM将被解密到DER,然后调用importKeyDER函数。如果提供的密码不正确,生成的DER表示格式也不正确,您将得到一个您提供的异常。为了证实这一点,我在下面做了两个快速测试:
>>> 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 the PEM from the author, I've realized that Hypothesis #1 is not valid for his case. I still want to keep it here as one possible reason of import failure, so other users are aware.
在收到作者的PEM之后,我意识到假设1对他的案例是无效的。我仍然希望把它作为导入失败的一个可能原因,这样其他用户就知道了。
Hypothesis #2 - this is the author's case.
假设2 -这是作者的案例。
RSA.py looks for the following in PEM file to determine what kind of encryption was applied to PEM:
RSA。py在PEM文件中查找以下内容,以确定应用于PEM的加密类型:
Proc-Type: 4,ENCRYPTED
When key is generated using "openssl genrsa ..." command, this string is present in PEM in clear, however when "opensl genpkey ..." is used the "Proc-Type" is not present.
当使用“openssl genrsa…”命令生成密钥时,这个字符串在PEM中很清楚,但是当“opensl genpkey…”被使用时,“proc类型”就不存在了。
RSA.py doesn't even try to decrypt the PEM if the "Proc-Type" is not found:
RSA。如果没有找到“Proc-Type”,py甚至不会尝试解密PEM:
# The encrypted PEM format
if lines[1].startswith(b('Proc-Type:4,ENCRYPTED')):
DEK = lines[2].split(b(':'))
....
So, my conclusion at this time is that keys generated by "openssl genpkey" are not supported by PyCrypto v 2.6.1.
因此,我的结论是,由“openssl genpkey”生成的密钥不受PyCrypto v2.6.1的支持。
Important Update
重要更新
It does work in PyCrypto's latest version 2.7a1. You can download it from here: http://ftp.dlitz.net/pub/dlitz/crypto/pycrypto/pycrypto-2.7a1.tar.gz
它在PyCrypto的最新版本2.7a1中工作。您可以从这里下载: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>
#2
2
A quick update for those who seek to solve this problem without installing an experimental release of long-abandoned PyCrypto. The library can be safely replaced by pycryptodome (https://github.com/Legrandin/pycryptodome) - it can provide both a drop-in replacement for pycrypto, and it can be used as an alternative library as well (pycryptodomex).
对于那些试图解决这个问题的人来说,一个快速的更新,不需要安装一个实验性的释放已久的PyCrypto。这个库可以安全地被pycryptodome (https://github.com/Legrandin/pycryptodome)取代,它可以提供一个替代pycrypto的替代库,它也可以作为一个替代的库(pycryptodomex)。