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.