1

如何解码 DER/PEM 格式的 IPFS 私钥和公钥,可以与 pycryptodome 库(对于 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")

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

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

4

1 回答 1

2

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

首先,你需要明白 PrivateKey 和 PublicKey 变量的内容不仅仅是一个用 Base64 编码的纯密钥,它是用 ByteArray 序列化然后用 Base64 编码的 protobuf 对象。为了从中获取密钥,您首先需要获取此对象的模式,该模式可通过引用获得。

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

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

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 和它对应的类的名称(PublicKeyforpublicKeyPrivateKeyfor 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()
于 2019-01-19T22:27:54.557 回答