Python 如何在 PyCrypto 中使用加密的 RSA 私钥?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23848849/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use encrypted RSA private key with PyCrypto?
提问by STF
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.
导入公钥工作正常,但它没有加密。
采纳答案by Oleg Gryb
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-Type”不存在。
RSA.py doesn't even try to decrypt the PEM if the "Proc-Type" is not found:
如果未找到“Proc-Type”,RSA.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.
因此,我此时的结论是 PyCrypto v 2.6.1 不支持“openssl genpkey”生成的密钥。
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>
回答by Василий Севостьянов
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)。