2014-05-24 74 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)。