как преобразовать необработанный модуль и экспоненту в открытый ключ RSA (формат .pem)

У меня есть модуль и показатель степени открытого ключа RSA, встроенного в двоичный файл, и я пытаюсь извлечь весь большой двоичный объект и создать пригодный для использования открытый ключ .pem.

В настоящее время я извлекаю полные 260 байтов (4 байта для экспоненты, 256 байтов для модуля) и кодирую как base64. Я делаю это с помощью следующей команды оболочки:

tail -c $((filesize - start_of_key_data)) filename | head -c $size_of_key_data | base64 > outkey

Это дает мне следующую строку:

<<<<<< modulus & exponent extracted from binary file, base64-encoded >>>>>>

tZyrQA6cZFJfVm6FyXwtZaLQYg8EecuO+ObrHTwc8JO+XrgnpNAdmlhbAEPxSNnjwhNnbYGYGL4F
vzmnZXzZU71Key42HQPh1k2Zx1UDbrH5ciODKx1ZbuEx8K24SHnL1nY/H75hwhT/ZRRVGQDvYDT+
sgzw2vmV66+dflw1Zs8BLhqjLjczdHvjeVXsDRJ9Mvvd/dhFH8UlTf4JpLGya9nsNIfNBBIf1Lll
RWwCTiEIbaOMgWcLjLV/2tk/j5Dra/oQnVf/2hVsEF/hXEx41YjeEW/warweoDVG7zaxrHEc/k/r
ZCUCZKxf8nBKdqax/gRICvkG6e5xg2GQw0W/ZwABAAE=

Теперь, когда я беру пару ключей key.pem, из которых изначально были извлечены модуль и показатель степени, и отображаю общедоступную часть, например,

openssl rsa -in key.pem -pubout -out pubkey.pem

Я получаю эту строку (я пропустил строки верхнего и нижнего колонтитула:

<<<<<<<<< valid public key data extracted from keypair >>>>>>>>>

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtZyrQA6cZFJfVm6FyXwt
ZaLQYg8EecuO+ObrHTwc8JO+XrgnpNAdmlhbAEPxSNnjwhNnbYGYGL4FvzmnZXzZ
U71Key42HQPh1k2Zx1UDbrH5ciODKx1ZbuEx8K24SHnL1nY/H75hwhT/ZRRVGQDv
YDT+sgzw2vmV66+dflw1Zs8BLhqjLjczdHvjeVXsDRJ9Mvvd/dhFH8UlTf4JpLGy
a9nsNIfNBBIf1LllRWwCTiEIbaOMgWcLjLV/2tk/j5Dra/oQnVf/2hVsEF/hXEx4
1YjeEW/warweoDVG7zaxrHEc/k/rZCUCZKxf8nBKdqax/gRICvkG6e5xg2GQw0W/
ZwIDAQAB

Вы можете видеть, что ключевые данные, которые я извлек и закодировал в кодировке base64, на самом деле присутствуют в данных действительных данных открытого ключа, извлеченных из key.pem с помощью openssl. Однако в начале 45 символов, которых нет в моих собственных извлеченных данных -

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA

и последние 8 символов также различаются.

ZwIDAQAB

Может ли кто-нибудь дать совет о том, как преобразовать модуль и показатель степени в полезный открытый ключ?

(цель состоит в том, чтобы сделать это в сценарии bash, а не в python или C, как многие предлагают.)


person Erik Nyquist    schedule 19.12.2014    source источник


Ответы (1)


Команда, которую вы использовали, openssl rsa -in key.pem -pubout -out pubkey.pem, создает такую ​​структуру ASN.1:

SEQUENCE(2 elem)
  SEQUENCE(2 elem)
    OBJECT IDENTIFIER 1.2.840.113549.1.1.1
    NULL
  BIT STRING(1 elem)
    SEQUENCE(2 elem)
      INTEGER(2048 bit) 229263895356027367204242482830890190076375310244080661230946245232688…
      INTEGER 65537

(Вы можете увидеть структуру с помощью openssl asn1parse -in pubkey.pem или с помощью онлайн-декодера ASN.1).

В нем содержится:

  1. фиксированный заголовок (содержит все байты, определяя кодировку всей последовательности плюс кодировку модуля)
  2. модуль
  3. заголовок, определяющий кодировку экспоненты
  4. экспонента

Если у вас правильно собраны байты модуля и экспоненты, вы можете создать открытый ключ в форме, понятной OpenSSL, объединив эти четыре элемента. У вас уже есть первый более длинный заголовок. «Средний заголовок» - «02 03»:

  1. '02' для целого числа
  2. длина самого целого числа 3 байта (65537 = 01 00 01)

Если ваш модуль составляет 2048 бит (256 байтов), а показатель степени - 3 байта (чтобы поля длины оставались действительными), файл PEM может быть создан путем объединения этих четырех:

<header> <modulus> 0x02 0x03 <exponent>

Вот почему последние байты из двоичного дампа отличаются от вывода OpenSSL: извлеченные 260 байтов не содержат 02 03, а вместо этого записывают 65537 как 00 01 00 01 (а не 01 00 01, как в кодировке ASN.1).

Подводя итог, вы можете создать файл PEM следующим образом:

Преобразуйте извлеченный модуль + показатель обратно из base64 и извлеките их (обратите внимание на смещение байта 257, чтобы пропустить начальный нулевой байт 65537!):

echo 'tZyrQA6cZFJfVm6FyXwtZaLQYg8EecuO+ObrHTwc8JO+XrgnpNAdmlhbAEPxSNnjwhNnbYGYGL4FvzmnZXzZU71Key42HQPh1k2Zx1UDbrH5ciODKx1ZbuEx8K24SHnL1nY/H75hwhT/ZRRVGQDvYDT+sgzw2vmV66+dflw1Zs8BLhqjLjczdHvjeVXsDRJ9Mvvd/dhFH8UlTf4JpLGya9nsNIfNBBIf1LllRWwCTiEIbaOMgWcLjLV/2tk/j5Dra/oQnVf/2hVsEF/hXEx41YjeEW/warweoDVG7zaxrHEc/k/rZCUCZKxf8nBKdqax/gRICvkG6e5xg2GQw0W/ZwABAAE=' | base64 -d > modulus-exp.bin
dd if=modulus-exp.bin of=modulus.bin bs=1 count=256
dd if=modulus-exp.bin of=exponent.bin bs=1 skip=257 count=3

Создайте заголовки:

echo 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA' | base64 -d > header.bin
echo '02 03' | xxd -r -p > mid-header.bin

Соедините их вместе:

cat header.bin modulus.bin mid-header.bin exponent.bin > key.der

Преобразовать в PEM:

openssl pkey -inform der -outform pem -pubin -in key.der -out key.pem

Убедитесь, что вы получили рабочий ключ - проверив его с помощью декодера ASN.1 или

openssl asn1parse -in key.pem
openssl asn1parse -in key.pem -strparse 19
person Konstantin Shemyak    schedule 19.12.2014