Как декодировать закрытый и открытый ключ IPFS в формате DER / PEM? - PullRequest
0 голосов
/ 19 января 2019

как декодировать закрытый и открытый ключ IPFS в формате DER / PEM, который может работать с библиотекой 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

1 Ответ

0 голосов
/ 20 января 2019

Решение оказалось не таким простым, как мне показалось на первый взгляд.

Для начала вам нужно понять, что содержимое переменных PrivateKey и PublicKey - это не просто чистый ключ, закодированный в Base64., это объект protobuf, сериализованный в ByteArray, а затем закодированный в Base64.Чтобы получить ключ от него, вам сначала нужно получить схему этого объекта, которая доступна по ссылке .

Мы сохраняем этот файл и следуем инструкциям на эта страница .Короче говоря, я выполнил команду protoc --python_out=. crypto.proto, чтобы создать модуль Python с именем crypto_pb2.py.

Все приготовления завершены, и теперь перейдем к коду:

import crypto_pb2
import base64

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

Сначала необходимо декодироватьстрока base64 в байтовом массиве:

decoded = base64.b64decode(publicKey) 

Эта функция десериализует массив байтов в знакомый объект protobuf Python, я взял его из этого ответа и немного изменил:

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 и имя класса, которому он соответствует (PublicKey для publicKey и PrivateKey для privateKey), меня интересуетсвойство Data.

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

Теперь вы можете передать его в функцию import_key как ByteArray.Не выполнять дополнительные преобразования.

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