2014-05-24 58 views
6

我生成与OpenSSL的一个关键,从标准输入提供的密码:如何在PyCrypto中使用加密的RSA私钥?

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

有趣的是,从栈跟踪判断它试图以二进制DER格式导入它,而不是在PEM中。您确定提供了正确的文件吗? –

回答

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”不存在。

RSA.py甚至没有尝试解密PEM如果“过程型”未发现:

# The encrypted PEM format 
    if lines[1].startswith(b('Proc-Type:4,ENCRYPTED')): 
    DEK = lines[2].split(b(':')) 
    .... 

所以,我在这个时候的结论是,通过为“OpenSSL genpkey”生成的密钥PyCrypto v 2.6.1不支持。

重要更新

它在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> 
+0

你可以用这个键试试吗? :http://pastebin.com/tcKJjdmw密码是'123456'。它适用于我的命令:openssl rsa -inform PEM -outform PEM -in private-key.pem -pubout,但不能与PyCrypto一起使用。 – STF

+0

你使用什么版本的openssl? –

+0

再次检查RSA.py,发现它查找“Proc-Type:4,ENCRYPTED”。如果它没有找到它,它甚至不会将PEM视为加密的。这就是我的openssl生成的:“----- BEGIN RSA PRIVATE KEY ----- Proc-Type:4,ENCRYPTED DEK-Info:DES-EDE3-CBC,AC78286040A62849”。它看起来像openssl的较新版本使用更新的格式。尝试生成RSA密钥的旧方法:“openssl genrsa -des3 -out privkey.pem 2048” –

2

快速更新为那些谁寻求无需安装长期废弃PyCrypto的实验版本来解决这个问题。该库可以安全地用pycryptodome替换(https://github.com/Legrandin/pycryptodome) - 它可以提供对pycrypto的替代替代品,并且它也可以用作替代库(pycryptodomex)。