2019-03-26

Экспорт приватных ключей Гост. ч.2

Снова дошли руки до гостовских ключей.

Итак задача та же: нужно получить "бесплатно" закрытые ключи из "дефакто" стандартного гостовского провайдера в openssl.

Система Windows 10.0.17134.648
Ключ с привязанным секретным ключом установлен через CSP.

Запускаем certmgr.msc. Личное - Сертификаты.
Жмём ПКМ на сертификат с привязанным ключом гост (экспортируемым).
Все задачи - Экспорт.
Далее. - Да, экспортировать закрытый ключ - Далее
Файл обмена личной информацией - PKCS #12 (.PFX).
Галочки можно не трогать - но я снял все. Лишнее не надо.
Далее. Галочку на пароль. Вбиваем 123 и 123 в подтверждение.
Шифрование TripleDES-SHA1 (можно и AES256-SHA256 - hmac проверка будет чуть другой).
Далее - Имя файла выбираем 123-try3.pfx - Далее - "Экспорт выполнен" - Готово.

Файл с приватным ключом лежит на диске. Радуемся но не долго.

$ openssl pkcs12 -info -engine gost -password pass:123 -in 123-try3.pfx
engine "gost" set.
MAC: sha1, Iteration 2000
MAC length: 20, salt length: 20
PKCS7 Data
Shrouded Keybag: undefined, Iteration 2000
Bag Attributes
    localKeyID: 01 00 00 00
    friendlyName: 9d09886d-f53d-4e57-85b1-c3c25b0cd72e
    Microsoft CSP Name: Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider
Error outputting keys and certificates
25769902144:error:06074079:digital envelope routines:EVP_PBE_CipherInit:unknown pbe algorithm:crypto/evp/evp_pbe.c:95:TYPE=1.2.840.113549.1.12.1.80
25769902144:error:23077073:PKCS12 routines:PKCS12_pbe_crypt:pkcs12 algor cipherinit error:crypto/pkcs12/p12_decr.c:41:
25769902144:error:2306A075:PKCS12 routines:PKCS12_item_decrypt_d2i:pkcs12 pbe crypt error:crypto/pkcs12/p12_decr.c:94:

Встречает наш знакомый oid=1.2.840.113549.1.12.1.80.

$ openssl asn1parse -inform der -in 123-try3.pfx
    0:d=0  hl=4 l=1140 cons: SEQUENCE
    4:d=1  hl=2 l=   1 prim: INTEGER           :03
    7:d=1  hl=4 l=1072 cons: SEQUENCE
   11:d=2  hl=2 l=   9 prim: OBJECT            :pkcs7-data
   22:d=2  hl=4 l=1057 cons: cont [ 0 ]
   26:d=3  hl=4 l=1053 prim: OCTET STRING      [HEX DUMP]:
30820419308201D606092A864886F70D010701A08201C7048201C3308201BF308201BB060B2A864886F70D010C0A0102A081B23081AF3024060A2A864886F70D010C015030160410C16E378ABE17ADBC7C29E4F5EA4EEED9020207D0048186C4A7BE9F5DEC55369A1E0B357B2D052256F2052E10642B47CC8A567351E81584FFD7DCB7D2384EEC4566A02A67F9EF7504D7A8FA4CCC51722D53770F2B4B4D0667F030E9060A6C0F4ED3D73342C0C1C86FD9669E9808B98A372BC0AF8919CC502F9C74351C60B43AD89D6F4155035CDA5EBE92C36D3D2C8EA562F0F5584529552258AAC84CC43181F6301306092A864886F70D0109153106040401000000305706092A864886F70D010914314A1E4800390064003000390038003800360064002D0066003500330064002D0034006500350037002D0038003500620031002D00630033006300320035006200300063006400370032006530818506092B060104018237110131781E7600430072007900700074006F002D00500072006F00200047004F0053005400200052002000330034002E00310030002D0032003000300031002000430072007900700074006F006700720061007000680069006300200053006500720076006900630065002000500072006F007600690064006500723082023B06092A864886F70D010701A082022C048202283082022430820220060B2A864886F70D010C0A0103A08201F8308201F4060A2A864886F70D01091601A08201E4048201E0308201DC3082018BA0030201020208661C4EDBFE648D91300806062A8503020203301F310B30090603550406130252553110300E0603550403130770756232303031301E170D3139303332353136343330305A170D3230303332353136343330305A301F310B30090603550406130252553110300E06035504031307707562323030313063301C06062A8503020213301206072A85030202240006072A850302021E0103430004403271B0ABC9CC92142384D0B10ADCBC4124A1D5A9AFD440F6A99AADDD882E70CFDB9AED1682A945DF956E04F8C97E8333CF839B461353BED1A04CD99304372B71A381A83081A5300E0603551D0F0101FF0404030202DC301D0603551D250416301406082B0601050507030206082B06010505070304301D0603551D0E0416041475C3BDAB0E1B5534DD35457A201AC7F46DB1DF5530440603551D23043D303B801475C3BDAB0E1B5534DD35457A201AC7F46DB1DF55A123A421301F310B30090603550406130252553110300E0603550403130770756232303031300F0603551D13040830060101FF020101300806062A850302020303410056D6DF338FE5D629243277F31DB56FCB5B7CBCAF8EFD8F8644CCB7359EACCE86B02131C1A5029750F7D831B907000DFE38DFCD18A98203773384C18B4890FAD13115301306092A864886F70D0109153106040401000000
 1083:d=1  hl=2 l=  59 cons: SEQUENCE
 1085:d=2  hl=2 l=  31 cons: SEQUENCE
 1087:d=3  hl=2 l=   7 cons: SEQUENCE
 1089:d=4  hl=2 l=   5 prim: OBJECT            :sha1
 1096:d=3  hl=2 l=  20 prim: OCTET STRING      [HEX DUMP]:
BA88838B4D071952A12D2AE49E91B16E9D1E4719
 1118:d=2  hl=2 l=  20 prim: OCTET STRING      [HEX DUMP]:
767C58C151C9125E72367411A97E9E706C95905C
 1140:d=2  hl=2 l=   2 prim: INTEGER           :07D0

Из предыдущего поста понятно как проверить целостность pkcs7-data - тут алгоритм видимо стандартный - но я его привёл perl скриптом. Скрипт всё ещё работает. Пароль кодируем в UCS2 - размножаем и дополняем номером версии (3) и солью, хешируем SHA1 ROUNDS раз и делаем HMAC_SHA1.

Номером версии=03
ROUNDS=0x7D0 (2000)
SALT=767C58C151C9125E72367411A97E9E706C95905C
HMAC=BA88838B4D071952A12D2AE49E91B16E9D1E4719

Если выводить с "AES256-SHA256" меняем алгоритм суммы SHA256 и HMAC_SHA256.
Но всё равно никаких 3Des и AES в файле не используется.

$VER=3;
$PASS='123';
$ROUNDS=0x7D0;
$SALT=pack 'H*', '767C58C151C9125E72367411A97E9E706C95905C';
$SHA1_NEED=pack 'H*','BA88838B4D071952A12D2AE49E91B16E9D1E4719';
$BLOB=pack 'H*', <<EOF;
30820419308201D606092A864886F70D010701A08201C7048201C3308201BF308201BB060B2A864886F70D010C0A0102A081B23081AF3024060A2A864886F70D010C015030160410C16E378ABE17ADBC7C29E4F5EA4EEED9020207D0048186C4A7BE9F5DEC55369A1E0B357B2D052256F2052E10642B47CC8A567351E81584FFD7DCB7D2384EEC4566A02A67F9EF7504D7A8FA4CCC51722D53770F2B4B4D0667F030E9060A6C0F4ED3D73342C0C1C86FD9669E9808B98A372BC0AF8919CC502F9C74351C60B43AD89D6F4155035CDA5EBE92C36D3D2C8EA562F0F5584529552258AAC84CC43181F6301306092A864886F70D0109153106040401000000305706092A864886F70D010914314A1E4800390064003000390038003800360064002D0066003500330064002D0034006500350037002D0038003500620031002D00630033006300320035006200300063006400370032006530818506092B060104018237110131781E7600430072007900700074006F002D00500072006F00200047004F0053005400200052002000330034002E00310030002D0032003000300031002000430072007900700074006F006700720061007000680069006300200053006500720076006900630065002000500072006F007600690064006500723082023B06092A864886F70D010701A082022C048202283082022430820220060B2A864886F70D010C0A0103A08201F8308201F4060A2A864886F70D01091601A08201E4048201E0308201DC3082018BA0030201020208661C4EDBFE648D91300806062A8503020203301F310B30090603550406130252553110300E0603550403130770756232303031301E170D3139303332353136343330305A170D3230303332353136343330305A301F310B30090603550406130252553110300E06035504031307707562323030313063301C06062A8503020213301206072A85030202240006072A850302021E0103430004403271B0ABC9CC92142384D0B10ADCBC4124A1D5A9AFD440F6A99AADDD882E70CFDB9AED1682A945DF956E04F8C97E8333CF839B461353BED1A04CD99304372B71A381A83081A5300E0603551D0F0101FF0404030202DC301D0603551D250416301406082B0601050507030206082B06010505070304301D0603551D0E0416041475C3BDAB0E1B5534DD35457A201AC7F46DB1DF5530440603551D23043D303B801475C3BDAB0E1B5534DD35457A201AC7F46DB1DF55A123A421301F310B30090603550406130252553110300E0603550403130770756232303031300F0603551D13040830060101FF020101300806062A850302020303410056D6DF338FE5D629243277F31DB56FCB5B7CBCAF8EFD8F8644CCB7359EACCE86B02131C1A5029750F7D831B907000DFE38DFCD18A98203773384C18B4890FAD13115301306092A864886F70D0109153106040401000000
EOF

use Encode 'encode';
use Digest::SHA qw(hmac_sha1 sha1);
$KEY=encode('UCS-2BE', $PASS."\0");
$KEY=((pack'C',$VER) x 64) . substr($SALT x 4, 0, 64) . substr($KEY x 32, 0, 64);
$KEY=sha1($KEY) for 1..$ROUNDS;
$SHA1_GOT=hmac_sha1($BLOB, $KEY);
use v5.10;
say 'HMAC: ',unpack 'H*', $KEY;
say 'NEED: ',unpack 'H*', $SHA1_NEED;
say 'CALC: ',unpack 'H*', $SHA1_GOT;

Продолжаем. Берём в буфер обмена содержимое pkcs7-data - пишем в файл и парсим asn1.

$ xxd -r -p > 123-try3.pkcs7
(paste)

$ openssl asn1parse -inform der -in 123-try3.pkcs7
    0:d=0  hl=4 l=1049 cons: SEQUENCE
    4:d=1  hl=4 l= 470 cons: SEQUENCE
    8:d=2  hl=2 l=   9 prim: OBJECT            :pkcs7-data
   19:d=2  hl=4 l= 455 cons: cont [ 0 ]
   23:d=3  hl=4 l= 451 prim: OCTET STRING      [HEX DUMP]:
308201BF308201BB060B2A864886F70D010C0A0102A081B23081AF3024060A2A864886F70D010C015030160410C16E378ABE17ADBC7C29E4F5EA4EEED9020207D0048186C4A7BE9F5DEC55369A1E0B357B2D052256F2052E10642B47CC8A567351E81584FFD7DCB7D2384EEC4566A02A67F9EF7504D7A8FA4CCC51722D53770F2B4B4D0667F030E9060A6C0F4ED3D73342C0C1C86FD9669E9808B98A372BC0AF8919CC502F9C74351C60B43AD89D6F4155035CDA5EBE92C36D3D2C8EA562F0F5584529552258AAC84CC43181F6301306092A864886F70D0109153106040401000000305706092A864886F70D010914314A1E4800390064003000390038003800360064002D0066003500330064002D0034006500350037002D0038003500620031002D00630033006300320035006200300063006400370032006530818506092B060104018237110131781E7600430072007900700074006F002D00500072006F00200047004F0053005400200052002000330034002E00310030002D0032003000300031002000430072007900700074006F006700720061007000680069006300200053006500720076006900630065002000500072006F00760069006400650072
  478:d=1  hl=4 l= 571 cons: SEQUENCE
  482:d=2  hl=2 l=   9 prim: OBJECT            :pkcs7-data
  493:d=2  hl=4 l= 556 cons: cont [ 0 ]
  497:d=3  hl=4 l= 552 prim: OCTET STRING      [HEX DUMP]:
3082022430820220060B2A864886F70D010C0A0103A08201F8308201F4060A2A864886F70D01091601A08201E4048201E0308201DC3082018BA0030201020208661C4EDBFE648D91300806062A8503020203301F310B30090603550406130252553110300E0603550403130770756232303031301E170D3139303332353136343330305A170D3230303332353136343330305A301F310B30090603550406130252553110300E06035504031307707562323030313063301C06062A8503020213301206072A85030202240006072A850302021E0103430004403271B0ABC9CC92142384D0B10ADCBC4124A1D5A9AFD440F6A99AADDD882E70CFDB9AED1682A945DF956E04F8C97E8333CF839B461353BED1A04CD99304372B71A381A83081A5300E0603551D0F0101FF0404030202DC301D0603551D250416301406082B0601050507030206082B06010505070304301D0603551D0E0416041475C3BDAB0E1B5534DD35457A201AC7F46DB1DF5530440603551D23043D303B801475C3BDAB0E1B5534DD35457A201AC7F46DB1DF55A123A421301F310B30090603550406130252553110300E0603550403130770756232303031300F0603551D13040830060101FF020101300806062A850302020303410056D6DF338FE5D629243277F31DB56FCB5B7CBCAF8EFD8F8644CCB7359EACCE86B02131C1A5029750F7D831B907000DFE38DFCD18A98203773384C18B4890FAD13115301306092A864886F70D0109153106040401000000

Видим теперь два объекта - второй это сертификат - и нам не нужен. Ключ в первом "мешке". Повторяем для него процедуру.

$ xxd -r -p > 123-try3.pkcs8
(paste)
$ openssl asn1parse -inform der -in 123-try3.pkcs8
    0:d=0  hl=4 l= 447 cons: SEQUENCE
    4:d=1  hl=4 l= 443 cons: SEQUENCE
    8:d=2  hl=2 l=  11 prim: OBJECT            :pkcs8ShroudedKeyBag
   21:d=2  hl=3 l= 178 cons: cont [ 0 ]
   24:d=3  hl=3 l= 175 cons: SEQUENCE
   27:d=4  hl=2 l=  36 cons: SEQUENCE
   29:d=5  hl=2 l=  10 prim: OBJECT            :1.2.840.113549.1.12.1.80
   41:d=5  hl=2 l=  22 cons: SEQUENCE
   43:d=6  hl=2 l=  16 prim: OCTET STRING      [HEX DUMP]:
C16E378ABE17ADBC7C29E4F5EA4EEED9
   61:d=6  hl=2 l=   2 prim: INTEGER           :07D0
   65:d=4  hl=3 l= 134 prim: OCTET STRING      [HEX DUMP]:
C4A7BE9F5DEC55369A1E0B357B2D052256F2052E10642B47CC8A567351E81584FFD7DCB7D2384EEC4566A02A67F9EF7504D7A8FA4CCC51722D53770F2B4B4D0667F030E9060A6C0F4ED3D73342C0C1C86FD9669E9808B98A372BC0AF8919CC502F9C74351C60B43AD89D6F4155035CDA5EBE92C36D3D2C8EA562F0F5584529552258AAC84CC4
  202:d=2  hl=3 l= 246 cons: SET
  205:d=3  hl=2 l=  19 cons: SEQUENCE
  207:d=4  hl=2 l=   9 prim: OBJECT            :localKeyID
  218:d=4  hl=2 l=   6 cons: SET
  220:d=5  hl=2 l=   4 prim: OCTET STRING      [HEX DUMP]:01000000
  226:d=3  hl=2 l=  87 cons: SEQUENCE
  228:d=4  hl=2 l=   9 prim: OBJECT            :friendlyName
  239:d=4  hl=2 l=  74 cons: SET
  241:d=5  hl=2 l=  72 prim: BMPSTRING
  315:d=3  hl=3 l= 133 cons: SEQUENCE
  318:d=4  hl=2 l=   9 prim: OBJECT            :Microsoft CSP Name
  329:d=4  hl=2 l= 120 cons: SET
  331:d=5  hl=2 l= 118 prim: BMPSTRING

Вот мы и добрались до этого unknown gost 1.2.840.113549.1.12.1.80 штатными средствами openssl.

Если загрузить исходный pfx в онлайн просмотрщик - можно было увидеть всю структуру сразу.

    0 30 1140: SEQUENCE {
    4 02    1:  INTEGER 3
    7 30 1072:  SEQUENCE {
   11 06    9:   OBJECT IDENTIFIER data (1.2.840.113549.1.7.1)
   22 a0 1057:   [0] {
   26 04 1053:    OCTET STRING, encapsulates {
   30 30 1049:     SEQUENCE {
   34 30  470:      SEQUENCE {
   38 06    9:       OBJECT IDENTIFIER data (1.2.840.113549.1.7.1)
   49 a0  455:       [0] {
   53 04  451:        OCTET STRING, encapsulates {
   57 30  447:         SEQUENCE {
   61 30  443:          SEQUENCE {
   65 06   11:           OBJECT IDENTIFIER pkcs8ShroudedKeyBag (1.2.840.113549.1.12.10.1.2)
   78 a0  178:           [0] {
   81 30  175:            SEQUENCE {
   84 30   36:             SEQUENCE {
   86 06   10:              OBJECT IDENTIFIER pbeUnknownGost (1.2.840.113549.1.12.1.80)
   98 30   22:              SEQUENCE {
  100 04   16:               OCTET STRING
             :                c1 6e 37 8a be 17 ad bc 7c 29 e4 f5 ea 4e ee d9
  118 02    2:               INTEGER 2000
             :              }
             :             }
  122 04  134:             OCTET STRING
             :              c4 a7 be 9f 5d ec 55 36 9a 1e 0b 35 7b 2d 05 22
             :              56 f2 05 2e 10 64 2b 47 cc 8a 56 73 51 e8 15 84
             :              ff d7 dc b7 d2 38 4e ec 45 66 a0 2a 67 f9 ef 75
             :              04 d7 a8 fa 4c cc 51 72 2d 53 77 0f 2b 4b 4d 06
             :              67 f0 30 e9 06 0a 6c 0f 4e d3 d7 33 42 c0 c1 c8
             :              6f d9 66 9e 98 08 b9 8a 37 2b c0 af 89 19 cc 50
             :              2f 9c 74 35 1c 60 b4 3a d8 9d 6f 41 55 03 5c da
             :              5e be 92 c3 6d 3d 2c 8e a5 62 f0 f5 58 45 29 55
             :              22 58 aa c8 4c c4
             :            }
             :           }
  259 31  246:           SET {
  262 30   19:            SEQUENCE {
  264 06    9:             OBJECT IDENTIFIER localKeyId (1.2.840.113549.1.9.21)
  275 31    6:             SET {
  277 04    4:              OCTET STRING, encapsulates {
  279 01    0:               BOOLEAN true
             :              }
             :             }
             :            }
  283 30   87:            SEQUENCE {
  285 06    9:             OBJECT IDENTIFIER friendlyName (1.2.840.113549.1.9.20)
  296 31   74:             SET {
  298 1e   72:              BMPString "9d09886d-f53d-4e57-85b1-c3c25b0cd72e"
             :             }
             :            }
  372 30  133:            SEQUENCE {
  375 06    9:             OBJECT IDENTIFIER keyProviderNameAttr (1.3.6.1.4.1.311.17.1)
  386 31  120:             SET {
  388 1e  118:              BMPString "Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider"
             :             }
             :            }
             :           }
             :          }
             :         }
             :        }
             :       }
             :      }
  508 30  571:      SEQUENCE {
  512 06    9:       OBJECT IDENTIFIER data (1.2.840.113549.1.7.1)
  523 a0  556:       [0] {
  527 04  552:        OCTET STRING, encapsulates {
  531 30  548:         SEQUENCE {
  535 30  544:          SEQUENCE {
  539 06   11:           OBJECT IDENTIFIER certBag (1.2.840.113549.1.12.10.1.3)
  552 a0  504:           [0] {
  556 30  500:            SEQUENCE {
  560 06   10:             OBJECT IDENTIFIER x509Certificate (1.2.840.113549.1.9.22.1)
  572 a0  484:             [0] {
  576 04  480:              OCTET STRING, encapsulates {
  580 30  476:               SEQUENCE {
  584 30  395:                SEQUENCE {
  588 a0    3:                 [0] {
  590 02    1:                  INTEGER 2
             :                 }
  593 02    8:                 INTEGER
             :                  66 1c 4e db fe 64 8d 91
  603 30    8:                 SEQUENCE {
  605 06    6:                  OBJECT IDENTIFIER id-GostR3411-94-with-GostR3410-2001 (1.2.643.2.2.3)
             :                 }
  613 30   31:                 SEQUENCE {
  615 31   11:                  SET {
  617 30    9:                   SEQUENCE {
  619 06    3:                    OBJECT IDENTIFIER countryName (2.5.4.6)
  624 13    2:                    PrintableString "RU"
             :                   }
             :                  }
  628 31   16:                  SET {
  630 30   14:                   SEQUENCE {
  632 06    3:                    OBJECT IDENTIFIER commonName (2.5.4.3)
  637 13    7:                    PrintableString "pub2001"
             :                   }
             :                  }
             :                 }
  646 30   30:                 SEQUENCE {
  648 17   13:                  UTCTime Mon Mar 25 2019 19:43:00 GMT+0300 (Москва, стандартное время)
  663 17   13:                  UTCTime Wed Mar 25 2020 19:43:00 GMT+0300 (Москва, стандартное время)
             :                 }
  678 30   31:                 SEQUENCE {
  680 31   11:                  SET {
  682 30    9:                   SEQUENCE {
  684 06    3:                    OBJECT IDENTIFIER countryName (2.5.4.6)
  689 13    2:                    PrintableString "RU"
             :                   }
             :                  }
  693 31   16:                  SET {
  695 30   14:                   SEQUENCE {
  697 06    3:                    OBJECT IDENTIFIER commonName (2.5.4.3)
  702 13    7:                    PrintableString "pub2001"
             :                   }
             :                  }
             :                 }
  711 30   99:                 SEQUENCE {
  713 30   28:                  SEQUENCE {
  715 06    6:                   OBJECT IDENTIFIER id-GostR3410-2001 (1.2.643.2.2.19)
  723 30   18:                   SEQUENCE {
  725 06    7:                    OBJECT IDENTIFIER id-GostR3410-2001-CryptoPro-XchA-ParamSet (1.2.643.2.2.36.0)
  734 06    7:                    OBJECT IDENTIFIER id-GostR3411-94-CryptoProParamSet (1.2.643.2.2.30.1)
             :                   }
             :                  }
  743 03   67:                  BIT STRING, unused 0 bits, encapsulates {
  745 04   64:                   OCTET STRING
             :                    32 71 b0 ab c9 cc 92 14 23 84 d0 b1 0a dc bc 41
             :                    24 a1 d5 a9 af d4 40 f6 a9 9a ad dd 88 2e 70 cf
             :                    db 9a ed 16 82 a9 45 df 95 6e 04 f8 c9 7e 83 33
             :                    cf 83 9b 46 13 53 be d1 a0 4c d9 93 04 37 2b 71
             :                  }
             :                 }
  812 a3  168:                 [3] {
  815 30  165:                  SEQUENCE {
  818 30   14:                   SEQUENCE {
  820 06    3:                    OBJECT IDENTIFIER keyUsage (2.5.29.15)
  825 01    1:                    BOOLEAN true
  828 04    4:                    OCTET STRING, encapsulates {
  830 03    2:                     BIT STRING, unused 2 bits
             :                      110111B
             :                    }
             :                   }
  834 30   29:                   SEQUENCE {
  836 06    3:                    OBJECT IDENTIFIER extKeyUsage (2.5.29.37)
  841 04   22:                    OCTET STRING, encapsulates {
  843 30   20:                     SEQUENCE {
  845 06    8:                      OBJECT IDENTIFIER clientAuth (1.3.6.1.5.5.7.3.2)
  855 06    8:                      OBJECT IDENTIFIER emailProtection (1.3.6.1.5.5.7.3.4)
             :                     }
             :                    }
             :                   }
  865 30   29:                   SEQUENCE {
  867 06    3:                    OBJECT IDENTIFIER subjectKeyIdentifier (2.5.29.14)
  872 04   22:                    OCTET STRING, encapsulates {
  874 04   20:                     OCTET STRING
             :                      75 c3 bd ab 0e 1b 55 34 dd 35 45 7a 20 1a c7 f4
             :                      6d b1 df 55
             :                    }
             :                   }
  896 30   68:                   SEQUENCE {
  898 06    3:                    OBJECT IDENTIFIER authorityKeyIdentifier (2.5.29.35)
  903 04   61:                    OCTET STRING, encapsulates {
  905 30   59:                     SEQUENCE {
  907 80   20:                      [0]
             :                       75 c3 bd ab 0e 1b 55 34 dd 35 45 7a 20 1a c7 f4
             :                       6d b1 df 55
  929 a1   35:                      [1] {
  931 a4   33:                       [4] {
  933 30   31:                        SEQUENCE {
  935 31   11:                         SET {
  937 30    9:                          SEQUENCE {
  939 06    3:                           OBJECT IDENTIFIER countryName (2.5.4.6)
  944 13    2:                           PrintableString "RU"
             :                          }
             :                         }
  948 31   16:                         SET {
  950 30   14:                          SEQUENCE {
  952 06    3:                           OBJECT IDENTIFIER commonName (2.5.4.3)
  957 13    7:                           PrintableString "pub2001"
             :                          }
             :                         }
             :                        }
             :                       }
             :                      }
             :                     }
             :                    }
             :                   }
  966 30   15:                   SEQUENCE {
  968 06    3:                    OBJECT IDENTIFIER basicConstraints (2.5.29.19)
  973 04    8:                    OCTET STRING, encapsulates {
  975 30    6:                     SEQUENCE {
  977 01    1:                      BOOLEAN true
  980 02    1:                      INTEGER 1
             :                     }
             :                    }
             :                   }
             :                  }
             :                 }
             :                }
  983 30    8:                SEQUENCE {
  985 06    6:                 OBJECT IDENTIFIER id-GostR3411-94-with-GostR3410-2001 (1.2.643.2.2.3)
             :                }
  993 03   65:                BIT STRING, unused 0 bits
             :                 56 d6 df 33 8f e5 d6 29 24 32 77 f3 1d b5 6f cb
             :                 5b 7c bc af 8e fd 8f 86 44 cc b7 35 9e ac ce 86
             :                 b0 21 31 c1 a5 02 97 50 f7 d8 31 b9 07 00 0d fe
             :                 38 df cd 18 a9 82 03 77 33 84 c1 8b 48 90 fa d1
             :               }
             :              }
             :             }
             :            }
             :           }
 1060 31   21:           SET {
 1062 30   19:            SEQUENCE {
 1064 06    9:             OBJECT IDENTIFIER localKeyId (1.2.840.113549.1.9.21)
 1075 31    6:             SET {
 1077 04    4:              OCTET STRING, encapsulates {
 1079 01    0:               BOOLEAN true
             :              }
             :             }
             :            }
             :           }
             :          }
             :         }
             :        }
             :       }
             :      }
             :     }
             :    }
             :   }
             :  }
 1083 30   59:  SEQUENCE {
 1085 30   31:   SEQUENCE {
 1087 30    7:    SEQUENCE {
 1089 06    5:     OBJECT IDENTIFIER sha1 (1.3.14.3.2.26)
             :    }
 1096 04   20:    OCTET STRING
             :     ba 88 83 8b 4d 07 19 52 a1 2d 2a e4 9e 91 b1 6e
             :     9d 1e 47 19
             :   }
 1118 04   20:   OCTET STRING
             :    76 7c 58 c1 51 c9 12 5e 72 36 74 11 a9 7e 9e 70
             :    6c 95 90 5c
 1140 02    2:   INTEGER 2000
             :  }
             : }

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



PASS=123
SALT=C16E378ABE17ADBC7C29E4F5EA4EEED9
ROUNDS=0x7D0
ENCRYPTED KEYBAG:
C4A7BE9F5DEC55369A1E0B357B2D052256F2052E10642B47CC8A567351E81584FFD7DCB7D2384EEC4566A02A67F9EF7504D7A8FA4CCC51722D53770F2B4B4D0667F030E9060A6C0F4ED3D73342C0C1C86FD9669E9808B98A372BC0AF8919CC502F9C74351C60B43AD89D6F4155035CDA5EBE92C36D3D2C8EA562F0F5584529552258AAC84CC4


Получаем ключ для расшифровки (сорри - опять perl).

use Digest::GOST::CryptoPro qw(gost);
$KEY=encode('UCS-2LE', $PASS);
for ($i=1;$i<=$ROUNDS;$i++){$KEY=gost($KEY.$SALT.pack('n',$i))}
say 'PASSWORD=',unpack 'H*',$KEY;

Для предыдущих цифр получаем ключ:
KEY=c2bb428f981f30d8e623db786d9bd780e7d9f785a950211530142ae46fab8dce
Вот раунды хеширования если будете повторять: 310032003300 c16e378abe17adbc7c29e4f5ea4eeed9 0001 fb76e01671ac07908c159f59a0442815acaccc2e77fc25958b99a4626fc738fe c16e378abe17adbc7c29e4f5ea4eeed9 0002 cdae166434edddd770cbc0d7294f4031d83309206bc15a3089cbde622fba0ce7 c16e378abe17adbc7c29e4f5ea4eeed9 0003 ...
9350e6ec445712728c6d7c6c02efb9068f295a3f451af8df33613bfc42412d71 c16e378abe17adbc7c29e4f5ea4eeed9 07d0
Хеш сумму можно получить штатными средствами так:
$ echo 310032003300 c16e378abe17adbc7c29e4f5ea4eeed9 0001 | xxd -r -p > round1
$ gostsum round1
fe38c76f62a4998b9525fc772eccacac152844a0599f158c9007ac7116e076fb round1
$ openssl dgst -engine gost -md_gost94 -hex round1
md_gost94(round1)= fb76e01671ac07908c159f59a0442815acaccc2e77fc25958b99a4626fc738fe
gostsum есть в пакетах, собирается из gost engine от openssl (есть на github) да, и он выдаёт другой порядок байт, что надо учитывать.
Всё это было и в первой части - тут чуть подробнее.
Теперь продолжение:
Снимаем транспортную кодировку с помощью openssl.
Что используем:
Симметричный шифр: gost89 (он же magma)

MODE=CFB (Режим шифрования - он по умолчанию для gost89 в openssl)
IV (Начальный вектор): SALT(0:7) (соль больше блока шифрования магмы - для IV отрезаем её до 8 байт=16  шестнадцатеричных символов = 64 бита - или игнорируем warning)
IV=C16E378ABE17ADBC (игнорируем остаток 7C29E4F5EA4EEED9)
KEY (Ключ - получили выше) 256 бит = 32 байта = 64 hex цифры.
KEY=c2bb428f981f30d8e623db786d9bd780e7d9f785a950211530142ae46fab8dce
$ xxd -r -p > 123-try3.enc
(paste keybag C4A7BE9F5DEC55369A1E0B...)
$ CRYPT_PARAMS=1.2.643.2.2.31.1 openssl enc -engine gost -d -gost89 -in 123-try3.enc -out 123-try3.dec \
-K c2bb428f981f30d8e623db786d9bd780e7d9f785a950211530142ae46fab8dce  -iv C16E378ABE17ADBC7C29E4F5EA4EEED9
На всякий случай задали параметры шифрования через env CRYPT_PARAMS но по умолчанию они же стоят. Должны получить asn1 c экспортным ключом (первый asci символ "0").
$ openssl asn1parse -inform der -in 123-try3.dec
    0:d=0  hl=3 l= 131 cons: SEQUENCE     3:d=1  hl=2 l=   1 prim: INTEGER           :00     6:d=1  hl=2 l=  10 cons: SEQUENCE     8:d=2  hl=2 l=   6 prim: OBJECT            :GOST R 34.10-2001    16:d=2  hl=2 l=   0 prim: NULL    18:d=1  hl=2 l= 114 prim: OCTET STRING      [HEX DUMP]: 0720000024AA00004D41473120000000
306030580408FEF0268E68E6A7EA302804207987275594A59F491E62F636F794BDD49A5CD547E0D901DF3AD58DA9EFFC2657040468369E8AA022030205A0A01C06062A8503020262301206072A85030202240006072A850302021E010404B30785AA
Содержимое блоба - это то, что мы получаем, если экспорт приватного ключа сделать через winapi. То есть транспортную кодировку мы полностью сняли.
Осталось то что получили внутрь openssl прописать :)
Посмотрим что нам даёт криптопро в своей экспортной структуре.
Заголовок структуры 07 - PRIVATEKEYBLOB (06 - PUBLICKEY).
Такой параметр передаётся в функцию ExportKey.
000020 - размер ключа? Или тут всё таки 00002007 ?
АА24 - algid:
algInfo name:DH 34.10-2001
longName:GOST R 34.10-2001 256 DH
algId:43556(AA24)
type:KeyExchange
OID:1.2.643.2.2.98
OID.alg=43556(AA24)
OID_groupId:3:PUBKEY_ALG
4D414731 = MAG1 "Магический заголовок"?
00000020 - опять размер ключа?
Дальше в структуре снова идёт asn1.
Отрезаем заголовок и смотрим что там:
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
Или на онлайн сервисе:
    0 30   96: SEQUENCE {
    2 30   88:  SEQUENCE {
    4 04    8:   OCTET STRING
             :    fe f0 26 8e 68 e6 a7 ea
   14 30   40:   SEQUENCE {
   16 04   32:    OCTET STRING
             :     79 87 27 55 94 a5 9f 49 1e 62 f6 36 f7 94 bd d4
             :     9a 5c d5 47 e0 d9 01 df 3a d5 8d a9 ef fc 26 57
   50 04    4:    OCTET STRING
             :     68 36 9e 8a
             :   }
   56 a0   34:   [0] {
   58 03    2:    BIT STRING, unused 5 bits
             :     101B
   62 a0   28:    [0] {
   64 06    6:     OBJECT IDENTIFIER id-GostR3410-2001DH (1.2.643.2.2.98)
   72 30   18:     SEQUENCE {
   74 06    7:      OBJECT IDENTIFIER id-GostR3410-2001-CryptoPro-XchA-ParamSet (1.2.643.2.2.36.0)
   83 06    7:      OBJECT IDENTIFIER id-GostR3411-94-CryptoProParamSet (1.2.643.2.2.30.1)
             :     }
             :    }
             :   }
             :  }
   92 04    4:  OCTET STRING
             :   b3 07 85 aa
             : }

Вот это нам ещё предстоит расшифровать.
Шифрованный приватный ключ (ещё не совсем сам приватный ключ, годный для openssl):
7987275594A59F491E62F636F794BDD49A5CD547E0D901DF3AD58DA9EFFC2657
Размер уже совпадает с ожидаемым секретным ключом, т.е. тут работает
симметричный алгоритм и никакой дополнительной структуры больше нет.
(Матрёшки asn1 наконец закончились).
Соли, контрольные суммы или что-то ещё:
FEF0268E68E6A7EA
68369E8A
B30785AA

Отсылки на:
id-GostR3410-2001-CryptoPro-XchA-ParamSet
id-GostR3410-2001DH
id-GostR3411-94-CryptoProParamSet
Также тут поработали такие не(до)документированные алгоритмы:
CALG_PRO_EXPORT CALG_PRO12_EXPORT CALG_SIMPLE_EXPORT

Упоминается, что они "работают в соответствии с рекомендациями ТК26" -
но как обратить их работу надо ещё смотреть.

И надо помнить, что у нас есть пароль на экспорт (может быть и не участвует)
и публичный ключ (из сертификата).
Публичный ключ (получить легко)=
3271B0ABC9CC92142384D0B10ADCBC4124A1D5A9AFD440F6A99AADDD882E70CF DB9AED1682A945DF956E04F8C97E8333CF839B461353BED1A04CD99304372B71

Части приватного ключа (при экспорте приватного в формате PEM)=
00DC1DFB629158E86D246F26DADD3289562910A1D65FD74E523A636351B8C33D
4597BEC52D5D4704
(видимо что-то фокс зашифровал)
Экспорт приватного ключа фоксом в pkcs8 без шифра даёт вот это:
{
    privateKeyAlgorithm: {
        name: "GOST R 34.10-2001",
        id: "id-GostR3410-2001",
        namedCurve: "X-256-A",
        sBox: "D-A"
    },
    privateKey: [
        0x04, 0x20, 0x31, 0x96, 0x76, 0x58, 0xc0, 0x64, 0x7a, 0xcd, 0xbd, 0x2c, 0x8a, 0x8d, 0x55, 0xcc,
        0x03, 0x18, 0x03, 0x20, 0x8d, 0x94, 0x29, 0x2c, 0x16, 0x22, 0x1f, 0x68, 0xd9, 0xd7, 0xca, 0xa5,
        0xd7, 0x3e
    ]
}

Приватный ключ=
042031967658C0647ACDBD2C8A8D55CC031803208D94292C16221F68D9D7CAA5D73E
Осталось это получить из шифрованного ключа.
...

Дополнения.

По адресу: https://tc26.ru/standard/rs/%D0%A0%2050.1.111-2016.pdf https://www.s-terra.ru/upload/medialibrary/9bb/rekomendacii-po-standartizacii-kriptografia.pdf нашлось описание хотелок ТК26, оформленных в виде
РЕКОМЕНДАЦИИ ПО СТАНДАРТИЗАЦИИ
ИСПОЛЬЗОВАНИЕ КРИПТОГРАФИЧЕСКИХ АЛГОРИТМОВ,
СОПУТСТВУЮЩИХ ПРИМЕНЕНИЮ СТАНДАРТОВ
ГОСТ Р 34.10-2012 И ГОСТ Р 34.11-2012
Утверждены решением заседания
технического комитета по стандартизации
«Криптографическая защита информации»
(Протокол №13 от 24.04.2014 г.)
В которых в пункте 5.6 "Экспорт и импорт ключей" дают такой алгоритм :
1) Порождается случайный набор UKM.
2) С помощью функции диверсификации, использующей в качестве ключа диверсификации ключ экспорта Ke,
и в качестве значения seed случайный набор UKM, производится формирование ключа, обозначаемого KEKe(UKM).
KEKe(UKM) = KDF(Ke,label,UKM).
3) Вычисляется значение имитовставки по ГОСТ 28147-89 длины 4 байта от данных K
на ключе KEKe(UKM), синхропосылка при этом полагается равной первым 8 байтам
UKM. Полученный набор обозначается через CEK_MAC.
Compute a 4-byte checksum value, gost28147IMIT (UKM, KEK(UKM), CEK).  Call the result CEK_MAC. [rfc4357]
4) Ключ K зашифровывается по алгоритму ГОСТ 28147-89 в режиме простой замены
с использованием ключа KEKe(UKM). Результат зашифрования обозначается через
CEK_ENC.
Encrypt CEK in ECB mode using KEK(UKM).  Call the ciphertext CEK_ENC. [rfc4357]
5) Экспортным представлением ключа полагается набор (UKM | CEK_ENC | CEK_MAC).

входной набор для порождения ключа: KDF(Ke,label,UKM)
выходной набор: UKM, CEK_ENC, CEK_MAC

label=26BDB878 (фиксированный набор - приведён в "рекомендациях")
UKM=FEF0268E68E6A7EA (очевидно самая длинная посылка, т.к. её размер минимум 8 байт)
CEK_ENC=7987275594A59F491E62F636F794BDD49A5CD547E0D901DF3AD58DA9EFFC2657
CEK_MAC=68369E8A или B30785AA (обе цифры длинной 4 байта - и могут быть MAC)
В секции 5.4 дают функцию диверсификации KDF_GOSTR3411_2012_256:
KDF(Kin,label,seed) = HMAC256(Kin,0x01|label|0x00|seed|0x01|0x00)
Осталось "угадать" значение Ke Читаем rfc4357 как "изуродовать" K до Ke:
6.5.  CryptoPro KEK Diversification Algorithm

   Given a random 64-bit UKM and a GOST 28147-89 key K, this algorithm
   creates a new GOST 28147-89 key K(UKM).

    1) Let K[0] = K;
    2) UKM is split into components a[i,j]:
       UKM = a[0]|..|a[7] (a[i] - byte, a[i,0]..a[i,7] - it's bits)
    3) Let i be 0.
    4) K[1]..K[8] are calculated by repeating the following algorithm
       eight times:
     A) K[i] is split into components k[i,j]:
        K[i] = k[i,0]|k[i,1]|..|k[i,7] (k[i,j] - 32-bit integer)
     B) Vector S[i] is calculated:
        S[i] = ((a[i,0]*k[i,0] + ... + a[i,7]*k[i,7]) mod 2^32) |
        (((~a[i,0])*k[i,0] + ... + (~a[i,7])*k[i,7]) mod 2^32);
     C) K[i+1] = encryptCFB (S[i], K[i], K[i])
     D) i = i + 1
    5) Let K(UKM) be K[8].

7.  Secret Key Diversification

   This algorithm creates a GOST 28147-89 key Kd, given GOST R 34.10-94
   or GOST R 34.10-2001 secret key K and diversification data D of size
   4..40 bytes.

    1) 40-byte blob B is created from D by cloning it enough times to
       fill all 40 bytes.  For example, if D is 40-bytes long, B = D; If
       D is 6-bytes long, B = D|D|D|D|D|D|D[0..3].
    2) B is split into 8-byte UKM and 32-byte SRCKEY (B = UKM|SRCKEY).
    3) The algorithm from Section 6.5 is used to create K(UKM) from key
       K and UKM, with two differences:
         * Instead of S[i], vector (0,0,0,UKM[i],ff,ff,ff,ff XOR UKM[i])
           is used.
         * During each encryption step, only 8 out of 32 GOST 28147-89
           rounds are done.
    4) Kd is calculated:
       Kd = encryptCFB (UKM, K(UKM), SRCKEY).
Лезем в код github/gost_engine Внутри test_keyexpimp.c проверочные значения одного из тестовых примеров из pdf tc26.
    unsigned char kdftree_key[] = {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
        0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
        0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
    };

    unsigned char kdf_label[] = { 0x26, 0xBD, 0xB8, 0x78 };
    unsigned char kdf_seed[] =  { 0xAF, 0x21, 0x43, 0x41, 0x45, 0x65, 0x63, 0x78 };
    const unsigned char kdf_etalon[] = {
        0x22, 0xB6, 0x83, 0x78, 0x45, 0xC6, 0xBE, 0xF6,
        0x5E, 0xA7, 0x16, 0x72, 0xB2, 0x65, 0x83, 0x10,
        0x86, 0xD3, 0xC7, 0x6A, 0xEB, 0xE6, 0xDA, 0xE9,
        0x1C, 0xAD, 0x51, 0xD8, 0x3F, 0x79, 0xD1, 0x6B,
        0x07, 0x4C, 0x93, 0x30, 0x59, 0x9D, 0x7F, 0x8D,
        0x71, 0x2F, 0xCA, 0x54, 0x39, 0x2F, 0x4D, 0xDD,
        0xE9, 0x37, 0x51, 0x20, 0x6B, 0x35, 0x84, 0xC8,
        0xF4, 0x3F, 0x9E, 0x6D, 0xC5, 0x15, 0x31, 0xF9
    };

// код проверки:
    ret = gost_kdftree2012_256(kdf_result, 64, kdftree_key, 32, kdf_label, 4, kdf_seed, 8, 1);
    if (ret <= 0) {
        ERR_print_errors_fp(stderr);
 err = 5;
    } else {
        hexdump(stdout, "KDF TREE", kdf_result, 64);
        if (memcmp(kdf_result, kdf_etalon, 64) != 0) {
            fprintf(stdout, "ERROR! test failed\n");
     err = 6;
        }
    }

// добавляем "первое" контрольное значение:
    const unsigned char kdf_gost_etalon[] = {
 0xa1, 0xaa, 0x5f, 0x7d, 0xe4, 0x02, 0xd7, 0xb3,
 0xd3, 0x23, 0xf2, 0x99, 0x1c, 0x8d, 0x45, 0x34,
 0x01, 0x31, 0x37, 0x01, 0x0a, 0x83, 0x75, 0x4f,
 0xd0, 0xaf, 0x6d, 0x7c, 0xd4, 0x92, 0x2e, 0xd9
    };

// и его код проверки:
    ret = gost_kdftree2012_256(kdf_result, 32, kdftree_key, 32, kdf_label, 4, kdf_seed, 8, 1);
    if (ret <= 0) {
        ERR_print_errors_fp(stderr);
 err = 9;
    } else {
        hexdump(stdout, "KDF_GOSTR3411_2012_256", kdf_result, 32);
        if (memcmp(kdf_result, kdf_gost_etalon, 32) != 0) {
            fprintf(stdout, "ERROR! test failed\n");
     err = 10;
        }
    }
Работающий код для вычисления KDF() у нас есть. Внутри gost_keywrap.c обнаруживаем функции деривации ключа. Контрольных значений не видно.
Находим контрольные примеры в рекомендациях (5.7 п13):
13) Экспорт и импорт ключей
на параметрах szOID_Gost28147_89_TC26_Z_ParamSet
Ключ K:

 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
Величина UKM:
af 21 43 41 45 65 63 78
label:
26 bd b8 78
 KEKe(UKM) = KDF(Ke,label,UKM):

 a1 aa 5f 7d e4 02 d7 b3 d3 23 f2 99 1c 8d 45 34
 01 31 37 01 0a 83 75 4f d0 af 6d 7c d4 92 2e d9
 CEK_MAC:
 38 d5 8a a3
 CEK_ENC:
 b9 fb 92 42 95 0f 84 3f 0f bd 5b 9a 5e cf 9f 17
 f7 9e 6d 21 58 16 56 de 6d c5 85 dd 62 7a 44 0a
K=042031967658C0647ACDBD2C8A8D55CC031803208D94292C16221F68D9D7CAA5D73E