Криптография
October 2, 2022

Побег из КриптоПро или же 1.2.840.113549.1.12.1.80

Думаю знакомая ситуация некоторым людям: Экспортируем контейнер в PFX(P12) и при попытке работы с ним получаем ошибку:

$ openssl pkcs12 -in csp.pfx 
Enter Import Password:
Bag Attributes
    localKeyID: 01 00 00 00 
    Microsoft CSP Name: Crypto-Pro GOST R 34.10-2012 KC1 CSP
    friendlyName: ****_*****_00.00.22_00.00.00
Error outputting keys and certificates
EVP_PBE_CipherInit:unknown pbe algorithm:../crypto/evp/evp_pbe.c:95:TYPE=1.2.840.113549.1.12.1.80
PKCS12_pbe_crypt:pkcs12 algor cipherinit error:../crypto/pkcs12/p12_decr.c:41:
PKCS12_item_decrypt_d2i:pkcs12 pbe crypt error:../crypto/pkcs12/p12_decr.c:94:

Сегодня я покажу вам частичное решение данной проблемы(частичное из за лени разработчика гостовского движка для OpenSSL).

Заходим на GostCrypto и открываем наш PFX (P12):

В данном случае c1 6e 37 8a be 17 ad bc 7c 29 e4 f5 ea 4e ee d9 - это соль, 2000 - количество итераций, а c4 a7 be ... c8 4c c4 - зашифрованный шифром криптопро ключ.

Берем и качаем скрипт на Go и открываем его и меняем значения переменных на:

PASS :="123"; // - Ваш пароль от PFX/P12
SALT := "C16E378ABE17ADBC7C29E4F5EA4EEED9" // Соль, соответственно

После запуска скрипта мы получим ключ и соль для Магмы (он же ГОСТ 28187-89):

KEY  = c2bb428f981f30d8e623db786d9bd780e7d9f785a950211530142ae46fab8dce
SALT = C16E378ABE17ADBC

Записываем шифрованный ключ в KEY.in и через OpenSSL декодируем:

openssl enc -engine gost -d -gost89 -in KEY.in -out KEY.out -nosalt -K ключ -iv солб

В случае успеха в файле KEY.out будет лежать практически расшифрованный криптоключ:

    0:d=0  hl=2 l=  96 cons: SEQUENCE          
    2:d=1  hl=2 l=  88 cons: SEQUENCE          
    4:d=2  hl=2 l=   8 prim: OCTET STRING      [HEX DUMP]:FEF0268E68E6A7EA
   14:d=2  hl=2 l=  40 cons: SEQUENCE          
   16:d=3  hl=2 l=  32 prim: OCTET STRING      [HEX DUMP]:7987275594A59F491E62F636F794BDD49A5CD547E0D901DF3AD58DA9EFFC2657
   50:d=3  hl=2 l=   4 prim: OCTET STRING      [HEX DUMP]:68369E8A
   56:d=2  hl=2 l=  34 cons: cont [ 0 ]        
   58:d=3  hl=2 l=   2 prim: BIT STRING        
   62:d=3  hl=2 l=  28 cons: cont [ 0 ]        
   64:d=4  hl=2 l=   6 prim: OBJECT            :GOST R 34.10-2001 DH
   72:d=4  hl=2 l=  18 cons: SEQUENCE          
   74:d=5  hl=2 l=   7 prim: OBJECT            :id-GostR3410-2001-CryptoPro-XchA-ParamSet
   83:d=5  hl=2 l=   7 prim: OBJECT            :id-GostR3411-94-CryptoProParamSet
   92:d=1  hl=2 l=   4 prim: OCTET STRING      [HEX DUMP]:B30785AA

Данная структура это "блоб" приватного ключа, который описан в рекомендациях ТК-26 и отсюда можно выделить следующие поля:

UKM = FEF0268E68E6A7EA
CEK_ENC = 7987275594A59F491E62F636F794BDD49A5CD547E0D901DF3AD58DA9EFFC2657
CEK_MAC = 68369E8A

Как я понял из рекомендаций необходимо сделать unwrap ключа, GoGost не умеет это делать, но зато умеет PyGost, сделав указав параметры выше и KEY получил 31967658c0647acdbd2c8a8d55cc031803208d94292c16221f68d9d7caa5d73e . В каком направлении двигаться дальше понятия не имею.

Стоит также отметить что гостовский движок для OpenSSL поддерживает расшифровку данного "блоба", но как отметил vGimly, так и я убедился в личном разговоре - автор движка полностью незаинтересован в данной затее. Такие вот дела. To be continued....

UPD#1 - как оказалось я немножко слепой и не обратил внимание что результат unwrap это и есть приватный ключ, только вместо 04 в начале стоит 3, получается в итоге приватный ключ 042031967658C0647ACDBD2C8A8D55CC031803208D94292C16221F68D9D7CAA5D73E таким образом тему можно считать закрытой

UPD#2 - Как выяснилось это все работало только на ГОСТ 2001, а на ГОСТ 2012 это не работает :)

Ссылки

Статья vGimly - https://vgimly.blogspot.com/2019/03/2.html
Мой телеграмм канал - https://t.me/li0ard_notes