Как загрузить открытый ключ и экспоненту RSA512 из файла .bin в python - PullRequest
1 голос
/ 13 апреля 2019

У меня проблемы с загрузкой открытого ключа RSA512 из файла .bin в python. Проблема в основном связана с тем, что я не знаю, в каком формате хранится ключ. Это единственное описание файла, который мне дали.

"key.bin - необработанные двоичные байты 512-битного открытого ключа RSA и экспоненты. Используется для проверки подписи входящих пакеты ".

Я не знаю, полезно ли это, но здесь напечатаны байты на python файла .bin.

9902c4a66b1ff76392919e7bbc35d51a5128b9da03e131b489d5ed01c1d075fc4c139a9952e9a3b040d984219a4aef0d421f6b8f9c79e1c3c35a218ecba54dc9010001

Целью настоящей задачи является создание сервера udp, который проверяет цифровую подпись и целостность входящего пакета. В настоящее время я использую Python 2.7 с библиотекой криптографии. Документация может быть найдена ниже. https://cryptography.io/en/latest/hazmat/primitives/asymmetric/rsa/?highlight=rsa%20512

Я уже пробовал код ниже, но я получаю ту же ошибку для первых двух форматов и немного другую для третьего.

with open("key.bin", "rb") as key_file:
    private_key = serialization.load_der_public_key(key_file.read(), backend=default_backend())

ValueError: Could not deserialize key data.

with open("key.bin", "rb") as key_file:
    private_key = serialization.load_pem_public_key(key_file.read(), backend=default_backend())

ValueError: Could not deserialize key data.

with open("key.bin", "rb") as key_file:
    private_key = serialization.load_ssh_public_key(key_file.read(), backend=default_backend())

ValueError: Key is not in the proper format or contains extra data.

Также для проверки используется алгоритм хеширования SHA256, но это, вероятно, не имеет значения.

Ответы [ 2 ]

1 голос
/ 15 апреля 2019

Ваш ключ не закодирован в известном стандарте.Вам нужно извлечь модуль и экспоненту, а затем построить из них открытый ключ.

Модуль определяет размер ключа RSA и, следовательно, составляет 512 бит или 64 байта в качестве беззнакового старшего байтазначение.Публичный показатель может иметь любой размер, но обычно он небольшой.Наиболее используемое значение показателя степени - 010001 в шестнадцатеричных числах, которое является пятым простым числом Ферма (также называемое F4, индекс на основе нуля).Однако лучше просто получить первые 64 байта и предположить, что остальные коды являются открытыми показателями.

Таким образом, вы можете использовать RSAPublicNumbers для создания значений из модуля n и показателя e.Хитрость заключается в том, чтобы убедиться, что вы создаете модуль как положительное значение вместо отрицательного значения.


Предположим, что data - это двоичные данные, считанные из файла.Затем вы можете получить открытый ключ следующим образом.

Возможно, вы захотите использовать 'little' вместо 'big', если следующее не работает (big endian является значением по умолчанию RSA, но вы никогда не знаете,).Тем не менее, в вашем случае значение порядка байтов делится на, например, 11, так что это маловероятное значение модуля (простые значения должны быть близки к половине размера ключа в битах, чтобы быть защищенными).

modsize = 512 // 8

modBytes = data[slice(0, modsize)]
mod = int.from_bytes(modBytes, byteorder='big')

expBytes = data[slice(modsize, None)]
exp = int.from_bytes(expBytes, byteorder='big')

pubkey = RSAPublicNumbers(exp, mod).public_key(default_backend())

Обратите внимание, что from_bytes был добавлен только в Python 3.2.RSAPublicNumbers немного странно в том смысле, что он принимает параметр степени перед модулем.Любой другой API, который я видел, принимает модуль перед показателем степени.

1 голос
/ 14 апреля 2019

key.bin - Необработанные двоичные байты 512-битного открытого ключа RSA и экспоненты.Используется для проверки подписи входящих пакетов.

В ключе RSA-512 модуль представляет собой 512-битное число, которое помещается в 64 байта или 128 шестнадцатеричных цифр.Ваш файл представлен 134 шестнадцатеричными цифрами, поэтому вероятно, что 128 из этих цифр являются модулем, а остальные - открытым показателем и, возможно, метаданными.

Общий показатель почти всегда равен 3 или 65537 = 0x010001.Учитывая, что key.bin заканчивается на 010001 в шестнадцатеричном виде, разумно предположить, что последние 3 байта являются открытым показателем, а первые 64 байта являются модулем.

with open("key.bin", "rb") as key_file:
    n_bytes = key_file.read(64)
    e_bytes = key_file.read(3)

Теперь вам нужно выяснить,кодировка с прямым порядком байтов или с прямым порядком байтов.Вы не можете сказать от публичного экспонента, потому что это палиндромный.Попробуйте обе возможности:

n = int(n_bytes.encode('hex'), 16)

или

n = int(reversed(n_bytes).encode('hex'), 16)

Поскольку у вас есть ключ в специальном формате, а не в стандартном формате, который используется в реальной жизни, вывероятно, для работы с ключом использовались арифметические примитивы, а не криптографическая библиотека.

...