简体   繁体   中英

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

how to decode IPFS private and public key in DER/PEM format that can work with the pycryptodome library(for Python 3)? I get the keys from the IPFS configuration file as strings, so I will not explain this process here.

What I'm trying to do:

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()

I get the following exception:

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")

Similar problem with privateKey. In what format is the key and how to convert it to an acceptable format?

import_key function source code is there: https://github.com/Legrandin/pycryptodome/blob/master/lib/Crypto/PublicKey/RSA.py#L682

The solution was not as straightforward as it seemed to me at first glance.

For a start, you need to understand that the contents of the PrivateKey and PublicKey variables are not just a pure key encoded in Base64, it is a protobuf object serialized in ByteArray and then encoded in Base64. In order to get a key out of it, you first need to get a schema of this object, which is available by reference .

We save this file and follow the instructions on this page . In short, I ran the command protoc --python_out=. crypto.proto protoc --python_out=. crypto.proto to create a Python module called crypto_pb2.py .

All preparations are complete and now go to the code:

import crypto_pb2
import base64

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

You must first decode the base64 string to a byte array:

decoded = base64.b64decode(publicKey) 

This function deserializes an array of bytes into a familiar Python protobuf object, I took it from this answer and modified a little:

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

Further we call the function, pass the decoded base64 and the name of the class to which it corresponds ( PublicKey for publicKey and PrivateKey for privateKey ), I'm interested in the Data property.

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

Now you can transfer it to the import_key function as ByteArray. Do not perform additional conversions.

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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM