我正在使用OpenSSL生成密钥,从stdin提供密码:
openssl genpkey -algorithm RSA -out private-key.pem -outform PEM -pass stdin -des3 -pkeyopt rsa_keygen_bits:4096
键如下:
-----BEGIN ENCRYPTED PRIVATE KEY-----
XXX...
-----END ENCRYPTED PRIVATE KEY-----
我的Python代码如下:
from Crypto.PublicKey import RSA
# ...
f = open('private-key.pem', 'r')
r = RSA.importKey(f.read(), passphrase='some-pass')
f.close()
但我得到一个例外:
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
怎么了?
是否可以生成加密的RSA密钥,将其存储在文件中,然后将其与PyCrypto一起使用?是否可以使用OpenSSL?支持哪些格式?
导入公钥工作正常,但未加密。
答案 0 :(得分:4)
假设#1
在查看源代码之后,我想,我解开了这个谜。使用密码加密的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>
在收到作者的PEM后,我意识到假设#1对他的案件无效。我仍然希望将其保留在这里作为导入失败的一个可能原因,因此其他用户都知道。
假设#2 - 这是作者的案例。
RSA.py在PEM文件中查找以下内容,以确定对PEM应用了哪种加密:
Proc-Type: 4,ENCRYPTED
当使用“openssl genrsa ...”命令生成密钥时,此字符串以明文形式存在于PEM中,但是当使用“opensl genpkey ...”时,“Proc-Type”不存在。
如果找不到“Proc-Type”,RSA.py甚至不会尝试解密PEM:
# The encrypted PEM format
if lines[1].startswith(b('Proc-Type:4,ENCRYPTED')):
DEK = lines[2].split(b(':'))
....
所以,我此时的结论是PyCrypto v 2.6.1不支持“openssl genpkey”生成的密钥。
重要更新
它在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>
答案 1 :(得分:2)
为那些寻求解决此问题的人提供快速更新,而无需安装长期放弃的PyCrypto的实验版本。可以通过pycryptodome(https://github.com/Legrandin/pycryptodome)安全地替换该库 - 它既可以替代pycrypto,也可以用作替代库(pycryptodomex)。