簡體   English   中英

如何使用Python的加密模塊加載RSA公鑰

[英]How to load a RSA public key using Python's cryptography module

我正在嘗試使用加密模塊加載公鑰,這就是密鑰的樣子:

>>> print(pubkey)
-----BEGIN RSA PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+6gvHdCUCjnc4hSMwbdIIspk4
69pVAzjjb8tDJsCH/QpiK9vXe4nDZ7p9kiw2ACw0fkWaPnApKBwXNB9Nd9Sf+XFt
cIzdqKKBcAqZZCu2pA729amNRug9DoZdkstaBG+VfTxXhdzQRSTxxqJQWgdV8ejK
kt4D1M6pAiTkAyD0eQIDAQAB
-----END RSA PUBLIC KEY-----

我正在嘗試使用load_pem_public_key()方法加載它:

>>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives.serialization import load_pem_public_key
>>> load_pem_public_key(pubkey, default_backend())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/elias/.virtualenvs/ckpypkg/local/lib/python2.7/site-packages/cryptography/hazmat/primitives/serialization.py", line 24, in load_pem_public_key
    return backend.load_pem_public_key(data)
  File "/home/elias/.virtualenvs/ckpypkg/local/lib/python2.7/site-packages/cryptography/hazmat/backends/multibackend.py", line 285, in load_pem_public_key
    return b.load_pem_public_key(data)
  File "/home/elias/.virtualenvs/ckpypkg/local/lib/python2.7/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1376, in load_pem_public_key
    self._handle_key_loading_error()
  File "/home/elias/.virtualenvs/ckpypkg/local/lib/python2.7/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 1595, in _handle_key_loading_error
    raise ValueError("Could not unserialize key data.")
ValueError: Could not unserialize key data.

難道我做錯了什么? 這把鑰匙有問題嗎? 為什么它不能被反序列化?

OpenSSL版本:

$ openssl version
OpenSSL 1.0.1f 6 Jan 2014

更新:我剛剛使用不同的密鑰測試相同的代碼(與其他SO問題相同 )並且它工作,這使得這更令人費解:為什么它適用於該密鑰而不適用於我的?

您正在嘗試將密鑰視為PEM編碼的RSA密鑰,但實際上您擁有的是使用PKCS#1格式的公鑰。 -----BEGIN RSA PUBLIC KEY----------END RSA PUBLIC KEY-----之間的數據實際上只是base-64編碼的DER數據。 可能有一個庫函數來實現(我開始查看cryptography文檔,我的眼睛開始上釉),但以下將起作用...

我們從您的關鍵數據開始:

>>> print pubkey
-----BEGIN RSA PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+6gvHdCUCjnc4hSMwbdIIspk4
69pVAzjjb8tDJsCH/QpiK9vXe4nDZ7p9kiw2ACw0fkWaPnApKBwXNB9Nd9Sf+XFt
cIzdqKKBcAqZZCu2pA729amNRug9DoZdkstaBG+VfTxXhdzQRSTxxqJQWgdV8ejK
kt4D1M6pAiTkAyD0eQIDAQAB
-----END RSA PUBLIC KEY-----

我們刪除了BEGINEND行:

>>> b64data = '\n'.join(pubkey.splitlines()[1:-1])
>>> print b64data
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+6gvHdCUCjnc4hSMwbdIIspk4
69pVAzjjb8tDJsCH/QpiK9vXe4nDZ7p9kiw2ACw0fkWaPnApKBwXNB9Nd9Sf+XFt
cIzdqKKBcAqZZCu2pA729amNRug9DoZdkstaBG+VfTxXhdzQRSTxxqJQWgdV8ejK
kt4D1M6pAiTkAyD0eQIDAQAB

然后我們base64解碼數據:

>>> derdata = base64.b64decode(b64data)

現在我們有DER編碼的公鑰,所以我們可以將它提供給load_der_public_key

>>> from cryptography.hazmat.backends import default_backend
>>> from cryptography.hazmat.primitives.serialization import load_der_public_key
>>> key = load_der_public_key(derdata, default_backend())
>>> print key
<cryptography.hazmat.backends.openssl.rsa._RSAPublicKey object at 0x7fe590ea6d10>

長話短說,顯然你的PEM有PKCS#1格式的頁眉和頁腳( -----BEGIN RSA PUBLIC KEY----------END RSA PUBLIC KEY----- )但是包含PKCS#8格式的DER序列,因為load_pem_public_key無法正確地反序列化pem,因為它需要PKCS#1 DER格式,但接收PKCS#8格式。 通過用與PKCS#8格式相對應的頁眉和頁腳替換頁眉和頁腳來快速修復。

在您的pem文件中替換-----BEGIN RSA PUBLIC KEY----------BEGIN PUBLIC KEY----- ,以及-----END RSA PUBLIC KEY----- with -----END PUBLIC KEY-----

您的公鑰應如下所示:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+6gvHdCUCjnc4hSMwbdIIspk4
69pVAzjjb8tDJsCH/QpiK9vXe4nDZ7p9kiw2ACw0fkWaPnApKBwXNB9Nd9Sf+XFt
cIzdqKKBcAqZZCu2pA729amNRug9DoZdkstaBG+VfTxXhdzQRSTxxqJQWgdV8ejK
kt4D1M6pAiTkAyD0eQIDAQAB
-----END PUBLIC KEY-----

否則加密模塊將無法解析它。


編輯

-----BEGIN RSA PUBLIC KEY-----適用於PKCS#1, -----BEGIN PUBLIC KEY-----公鑰-----BEGIN PUBLIC KEY-----適用於PKCS#8

您可以通過執行以下操作檢查DER格式:

from Crypto.Util.asn1 import DerSequence
public_key_der = DerSequence()
public_key_der.decode('MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+6gvHdCUCjnc4hSMwbdIIspk469pVAzjjb8tDJsCH/QpiK9vXe4nDZ7p9kiw2ACw0fkWaPnApKBwXNB9Nd9Sf+XFtcIzdqKKBcAqZZCu2pA729amNRug9DoZdkstaBG+VfTxXhdzQRSTxxqJQWgdV8ejKkt4D1M6pAiTkAyD0eQIDAQAB'.decode('base64'));
for k,v in enumerate(public_key_der):
    print k, v

您會注意到您的public_key_der[0]是另一個DER序列(您實際上可以再次解碼它: public_key_der.decode(public_key_der[0]) ),並表示來自PKCS#8 DER格式的AlgorithmIdentifier序列,如果它是PKCS#1 public_key_der[0]應該有一個表示模數的INTEGER。

有關PKCS#8 vs PKCS#1格式的更多信息,請訪問: https//tls.mbed.org/kb/cryptography/asn1-key-structures-in-der-and-pem

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM