如何解码 DER/PEM 格式的 IPFS 私钥和 public 密钥?

How to decode IPFS private and public key in DER/PEM format?

如何解码可以与 pycryptodome 库一起使用的 DER/PEM 格式的 IPFS 私钥和 public 密钥(对于 Python 3)?我从IPFS的配置文件中获取的密钥都是字符串形式的,所以这里就不解释这个过程了。

我想做什么:

import base64, Crypto

publicKey = "CAASpgIwgE ... jkupAgMBAAE="
privateKey = "CAASqQkwgg ... Xmzva/Km7A=="

publicKey = base64.b64decode(publicKey)
key = Crypto.PublicKey.RSA.import_key(publicKey)
crypter = Crypto.Cipher.PKCS1_OAEPPKCS1_OAEP.new(key)
encryptedData = crypter.encrypt(data.encode())
result = base64.b64encode(encryptedData).decode()

我得到以下异常:

key = Crypto.PublicKey.RSA.importKey(publicKey)
  File "/usr/local/lib/python3.6/site-packages/Crypto/PublicKey/RSA.py", line 754, in import_key
    raise ValueError("RSA key format is not supported")

私钥有类似问题。密钥采用什么格式以及如何将其转换为可接受的格式?

import_key 函数源代码在那里:https://github.com/Legrandin/pycryptodome/blob/master/lib/Crypto/PublicKey/RSA.py#L682

解决方案并不像我第一眼看上去那么简单。

首先,您需要了解PrivateKey 和PublicKey 变量的内容不仅仅是用Base64 编码的纯密钥,它是用ByteArray 序列化然后用Base64 编码的protobuf 对象。为了从中获取密钥,您首先需要获取此对象的架构,可通过 reference.

我们保存此文件并按照 this page 上的说明进行操作。简而言之,我 运行 命令 protoc --python_out=. crypto.proto 创建一个名为 crypto_pb2.py 的 Python 模块。

所有准备工作完成,现在进入代码:

import crypto_pb2
import base64

publicKey = "CAASpgIwgE ... jkupAgMBAAE="
privateKey = "CAASqQkwgg ... Xmzva/Km7A=="

您必须先将 base64 字符串解码为字节数组:

decoded = base64.b64decode(publicKey) 

这个函数将一个字节数组反序列化为一个熟悉的Python protobuf 对象,我从 中取出并稍作修改:

def deserialize(byte_message, proto_type):
    module_, class_ = proto_type.rsplit('.', 1)
    class_ = getattr(crypto_pb2, class_) # crypto_pb2 is a name of module we recently created and imported
    rv = class_()
    rv.ParseFromString(byte_message) # use .SerializeToString() to reverse operation
    return rv

进一步我们调用该函数,传递解码的base64和它对应的class的名称(PublicKey代表publicKeyPrivateKey代表privateKey), 我对 Data 属性.

感兴趣
publicKey = deserialize(decoded, 'crypto.pb.PublicKey').Data

现在您可以运行将它作为 ByteArray 传递给 import_key 函数。不执行额外的转换。

key = Crypto.PublicKey.RSA.import_key(publicKey)
crypter = Crypto.Cipher.PKCS1_OAEPPKCS1_OAEP.new(key)
encryptedData = crypter.encrypt(data.encode())
result = base64.b64encode(encryptedData).decode()