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

STF*_*STF 6 python encryption rsa pycrypto private-key

我正在使用OpenSSL生成密钥,从stdin提供密码:

openssl genpkey -algorithm RSA -out private-key.pem -outform PEM -pass stdin -des3 -pkeyopt rsa_keygen_bits:4096
Run Code Online (Sandbox Code Playgroud)

键然后看起来像:

-----BEGIN ENCRYPTED PRIVATE KEY-----
XXX...
-----END ENCRYPTED PRIVATE KEY-----
Run Code Online (Sandbox Code Playgroud)

我的Python代码如下:

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

但我得到一个例外:

  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
Run Code Online (Sandbox Code Playgroud)

怎么了?

是否可以生成加密的RSA密钥,将其存储在文件中,然后将其与PyCrypto一起使用?是否可以使用OpenSSL?支持哪些格式?

导入公钥工作正常,但它没有加密.

Ole*_*ryb 5

假设#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>
Run Code Online (Sandbox Code Playgroud)

收到作者的 PEM 后,我意识到假设 1 对于他的案例无效。我仍然想将其保留在这里,作为导入失败的可能原因之一,以便其他用户知道。

假设#2——这是作者的案例。

RSA.py 在 PEM 文件中查找以下内容以确定对 PEM 应用了哪种加密:

 Proc-Type: 4,ENCRYPTED
Run Code Online (Sandbox Code Playgroud)

当使用“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(':'))
     ....
Run Code Online (Sandbox Code Playgroud)

所以,我此时的结论是 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>
Run Code Online (Sandbox Code Playgroud)