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

时间:2019-01-19 20:02:14

标签: python rsa pycrypto ipfs pycryptodome

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

1 个答案:

答案 0 :(得分:0)

解决方案并不像乍看起来那样简单。

首先,您需要了解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对象,我从this answer那里获取并进行了一些修改:

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及其对应的类的名称(PublicKeypublicKeyPrivateKeyprivateKey), '对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()