如何在PyCrypto中使用加密的RSA私钥?

时间:2014-05-24 19:27:42

标签: python encryption rsa private-key pycrypto

我正在使用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?支持哪些格式?

导入公钥工作正常,但未加密。

2 个答案:

答案 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)。