Как передать 44 байта ключа x25519 publi c, созданного openssl, в CryptoKit, для которого требуется длина ключа 32 байта - PullRequest
0 голосов
/ 19 февраля 2020

Предположим, что я создаю пару ключей x25519, используя openssl, она выведет закрытый ключ размером 64 байта и соответствующий кодируемый в Base64 ключ publi c, закодированный в Base64, который будет выглядеть как

-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VuBCIEIMBF8S7zUco4bRrMiIuyTcSYU/rAVlNtE8SMYWphUatw
-----END PRIVATE KEY-----


-----BEGIN PUBLIC KEY-----
MCowBQYDK2VuAyEAE0eiiP0PKjy9AVM/0z2ZIZn453WSJNemrQ58HAXDaX0=
-----END PUBLIC KEY-----

Swift CryptoKit только принимать 32 байта для каждой, частной и общедоступной c инициализации ключа.

Если я правильно понял, закрытый ключ на 64 байта - это начальное число, где первые 32 байта являются действительным закрытым ключом.

Тем не менее, использование того же принципа для ключа publi c не работает (не очень удивительно)

Вопрос теперь заключается в следующем: как перевести ключ publi c в 32 байта? требуется Swift CryptoKit?

Вот неработающий пример использования первых 32 байт декодированного base64 ключа c

let base64PublicKey = Data(base64Encoded: "MCowBQYDK2VuAyEAE0eiiP0PKjy9AVM/0z2ZIZn453WSJNemrQ58HAXDaX0=")!.dropLast(12)

let publicKey = try! Curve25519.KeyAgreement.PublicKey(rawRepresentation: rawPublicKey) 

1 Ответ

2 голосов
/ 20 февраля 2020
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VuBCIEIMBF8S7zUco4bRrMiIuyTcSYU/rAVlNtE8SMYWphUatw
-----END PRIVATE KEY-----

per rfc7468 является незашифрованным PKCS8 PrivateKeyInfo , который закодирован в ASN.1 DER и содержит данные об алгоритме (и в целом но не здесь параметры), а также фактический ключ. Запуск этого в openssl asn1parse -i (который автоматически de-base64's) дает

    0:d=0  hl=2 l=  46 cons: SEQUENCE
    2:d=1  hl=2 l=   1 prim:  INTEGER           :00
    5:d=1  hl=2 l=   5 cons:  SEQUENCE
    7:d=2  hl=2 l=   3 prim:   OBJECT            :X25519
   12:d=1  hl=2 l=  34 prim:  OCTET STRING      [HEX DUMP]:0420C045F12EF351CA386D1ACC888BB24DC49853FAC056536D13C48C616A6151AB70

Алгоритм, определяемый алгоритмом c, является OCTETSTRING со значением по смещению 12 + 2 и длиной 34, но на самом деле содержит вложенная кодировка OCTETSTRING, первые два октета которой имеют значение 04 = tag и 20 = length, поэтому истинный закрытый ключ находится по смещению 16 с длиной 32 или, проще говоря, с последними 32 байтами.

-----BEGIN PUBLIC KEY-----
MCowBQYDK2VuAyEAE0eiiP0PKjy9AVM/0z2ZIZn453WSJNemrQ58HAXDaX0=
-----END PUBLIC KEY-----

аналогично - это структура SubjectPublicKeyInfo , определенная X.509 и PKIX, которая аналогично является DER и содержит данные в дополнение к ключу. Синтаксический анализ (с -dump) дает:

    0:d=0  hl=2 l=  42 cons: SEQUENCE
    2:d=1  hl=2 l=   5 cons:  SEQUENCE
    4:d=2  hl=2 l=   3 prim:   OBJECT            :X25519
    9:d=1  hl=2 l=  33 prim:  BIT STRING
      0000 - 00 13 47 a2 88 fd 0f 2a-3c bd 01 53 3f d3 3d 99   ..G....*<..S?.=.
      0010 - 21 99 f8 e7 75 92 24 d7-a6 ad 0e 7c 1c 05 c3 69   !...u.$....|...i
      0020 - 7d

Первый октет значения BITSTRING используется для количества неиспользуемых битов / битов, здесь 00, поэтому реальное значение publickey - 33-1 = 32 октета со смещением 9 + 2 + 1 = 12, или снова последние 32 байта.


Ed25519 хеширует приватный ключ для получения 32-байтового скаляра, иногда называемого начальным числом, и 32-байтового значение, которое определяет публичный ключ. Это начальное число может быть сохранено с помощью privatekey, чтобы сделать подпись более эффективной, но OpenSSL не делает этого для Ed25519 и совершенно не относится к X25519.

...