如何使用Python的加密模块加载RSA公钥

我正在尝试使用 cryptography模块加载公钥,这就是密钥的样子:
>>> 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 —– with —– END PUBLIC KEY —–

您的公钥应如下所示:

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

否则cryptography模块将无法解析它.

编辑

—– BEGIN RSA PUBLIC KEY —–适用于PKCS#1,—–开始公钥—–适用于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

相关文章

在这篇文章中,我们深入学习了XPath作为一种常见的网络爬虫技巧。XPath是一种用于定位和选择XML文档中特...
祝福大家龙年快乐!愿你们的生活像龙一样充满力量和勇气,愿你们在新的一年里,追逐梦想,勇往直前,不...
今天在爬虫实战中,除了正常爬取网页数据外,我们还添加了一个下载功能,主要任务是爬取小说并将其下载...
完美收官,本文是爬虫实战的最后一章了,所以尽管本文着重呈现爬虫实战,但其中有一大部分内容专注于数...
JSON是一种流行的数据传输格式,Python中有多种处理JSON的方式。官方的json库是最常用的,它提供了简单...
独立样本T检验适用于比较两组独立样本的均值差异,而配对T检验则适用于比较同一组样本在不同条件下的均...