如何使用Python的加密模块
我试图加载使用cryptography模块的公共密钥加载RSA公共密钥,这是关键的样子:如何使用Python的加密模块
>>> 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
更新:我只是测试相同的代码使用不同的密钥(同一个从this other SO question)和它的工作,这使得这个还更令人费解:为什么它适用于那个钥匙,而不是我的?
长话短说,显然你的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-----
与-----END PUBLIC KEY-----
你的公钥应该是这样的:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+6gvHdCUCjnc4hSMwbdIIspk4
69pVAzjjb8tDJsCH/QpiK9vXe4nDZ7p9kiw2ACw0fkWaPnApKBwXNB9Nd9Sf+XFt
cIzdqKKBcAqZZCu2pA729amNRug9DoZdkstaBG+VfTxXhdzQRSTxxqJQWgdV8ejK
kt4D1M6pAiTkAyD0eQIDAQAB
-----END PUBLIC KEY-----
否则cryptography模块将无法解析它。
编辑
-----BEGIN RSA PUBLIC KEY-----
是PKCS#1,-----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
您试图像对待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-----
我们放下BEGIN
和END
线:
>>> 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>
恩,你确定吗?因为那太奇怪了!你能指出任何确认这种行为的来源吗? – elias
这不能是原因,我刚刚测试了另一个关键(从[这个问题](http://stackoverflow.com/questions/10569189/how-to-read-a-rsa-public-key-in- peg-pkcs1-format) – elias
----- BEGIN RSA PUBLIC KEY -----用于PKCS#1标准,----- BEGIN PUBLIC KEY -----用于PKCS# 8标准,我对您的公钥进行了解码,并且它的der序列符合PKCS#8的序列。您可以在这里找到更多关于DER序列与PKCS#1和PKCS#8不同的信息:https://tls.mbed.org/kb/cryptography/asn1-key-structures-in-der-and-pem。顺便说一句,我在发布之前测试了我的答案,并且它工作正常,你应该至少在放弃之前尝试。 – godvsdeity