Вернуться к двоичному секретному ключу secp256k1 из шестнадцатеричного DER - PullRequest
2 голосов
/ 06 марта 2020

Я хочу получить private_key.pem из foo_priv.key

$ openssl ecparam -genkey -name secp256k1 -rand /dev/urandom -out private_key.pem   
$ openssl ec -in private_key.pem -outform DER|tail -c +8|head -c 32 |xxd -p -c 32 > foo_priv.key

Я пытался с

$ openssl ec -noout -text -inform DER -in foo_priv.key
read EC key
unable to load Key

$ openssl x509 -in foo_priv.key -inform DER -outform PEM
unable to load certificate
4486393452:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:1220:
4486393452:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error:tasn_dec.c:386:Type=X509

$ cat foo_priv.key | xxd -r -p  > test.bin  
$ openssl ec -in test.bin -inform DER -pubin -text -noout                
read EC key
unable to load Key
4456304236:error:0D06B08E:asn1 encoding routines:ASN1_D2I_READ_BIO:not enough data:a_d2i_fp.c:247:

1 Ответ

1 голос
/ 06 марта 2020

Ваши tail и head механизмы для извлечения приватной части вашего ключа дают вам только его байты. Однако OpenSSL нужно больше, чем для хранения информации о секретном ключе. Если вы используете OpenSSL 1.1.1, вы можете извлечь необходимые байты, используя опцию -no_public инструмента ec, например:

$ openssl ec -in private_key.pem -outform DER -no_public | xxd -p -c 32
read EC key
writing EC key
302e020101042031792710388085aaec53a04072a231116dc102e63cccdf5e85
ddd875cab6be6da00706052b8104000a

Сравнивая это с вашим оригинальным подходом, вы можете увидеть эта информация была потеряна там:

$ openssl ec -in private_key.pem -outform DER | tail -c +8 | head -c 32 | xxd -p -c 32
read EC key
writing EC key
31792710388085aaec53a04072a231116dc102e63cccdf5e85ddd875cab6be6d

Как правило, эти файлы хранятся в формате ASN.1, который вы не можете легко изменить, не нарушив его. Чтобы получить представление о дополнительной информации, которую вы удалили, вы можете использовать

$ openssl ec -in private_key.pem -no_public | openssl asn1parse
    0:d=0  hl=2 l=  46 cons: SEQUENCE          
    2:d=1  hl=2 l=   1 prim: INTEGER           :01
    5:d=1  hl=2 l=  32 prim: OCTET STRING      [HEX DUMP]:31792710388085AAEC53A04072A231116DC102E63CCCDF5E85DDD875CAB6BE6D
   39:d=1  hl=2 l=   7 cons: cont [ 0 ]        
   41:d=2  hl=2 l=   5 prim: OBJECT            :secp256k1

Обратите внимание на 32 байта в разделе OCTET STRING, которые именно вы извлекали. Но есть дополнительная информация о типе кривой, а также номер версии формата ключа. Это соответствует формату закрытого ключа E C, описанному в RF C 5915: Ellipti c Кривая структура секретного ключа , раздел 3. Без этой информации OpenSSL не может восстановить закрытый ключ.


Если вы все еще хотите восстановить файл личного ключа из 32 байтов ключа после прочтения всего этого, вы можете добиться этого с помощью (хрупкого) механизма добавления 302e0201010420 и добавления a00706052b8104000a и преобразования результат в двоичном виде. Что-то вроде

$ cat <(echo 302e0201010420) foo_priv.key <(echo a00706052b8104000a) | xxd -r -p | openssl ec -inform DER
read EC key
writing EC key
-----BEGIN EC PRIVATE KEY-----
MC4CAQEEIDF5JxA4gIWq7FOgQHKiMRFtwQLmPMzfXoXd2HXKtr5toAcGBSuBBAAK
-----END EC PRIVATE KEY-----
...