Собрал openssl 1.1.1 с внешней (теперь) библиотекой engine gost.
В perl использую Digest::GOST::Cryptopro и Crypt::GOST_PP. (Модуль от 2001 года Crypt::GOST не собирается. К тому же там нет кузнечика 2015 года - только Магма 89).
Итак, суть проблемы. Экспорт ключей из хранилища крипто-про через штатные средства системы делает нечитаемые openssl pkcs#12/p12/pfx.
Через утилитку P12FromGostCSP.exe лиссисофта (инфотекса) делаются (вроде) читаемые.
Генерируем через КриптоАРМ самоподписанный сертификат и импортируем его в хранилище.
Экспортируем через P12FromGostCSP в p12.pfx и успешно импортируем в Fox-XCA. После чего сохраняем из xca приватный ключ в нешифрованном PEM файле.
Для изучения проблемы удобно пользоваться ASN.1 Viewer и соответственно все манипуляции с ключами ведём только в бинарном DER формате (который на самом деле ASN.1 - в любом случае нам PEM/Base64 "обвязка" ни к чему).
Нашёл даже ещё более удобный онлайн сервис чтобы приводить асн1/сертификаты в JSON вид: http://gostcrypto.com/tool-syntax.html
Вот сам секретный ключ:
0 30 228: SEQUENCE { 3 06 9: OBJECT IDENTIFIER id-tc26-gost-3410-12-512-paramSetA (1.2.643.7.1.2.1.2.1) 14 06 8: OBJECT IDENTIFIER id-tc26-gost3411-12-512 (1.2.643.7.1.1.2.3) 24 04 64: OCTET STRING : 28 a1 3c 57 05 eb 32 9d b6 e7 ab c4 09 88 e1 74 : ca b3 df 19 35 bc 75 8a ea c0 da 35 08 bc ef dc : 02 91 7d d9 ef 0f e0 41 1e d1 9f 73 94 33 98 bb : 30 e9 9c 8b e0 d3 40 37 c8 52 e5 8d 50 ae 54 8d 90 04 8: OCTET STRING : 61 99 e9 f6 2d 67 fb d8 100 04 128: OCTET STRING : 5a da 7d 4e 4d 7a 24 6c 12 83 b0 57 9f b7 9f ca : b8 4b b0 ee 64 60 41 5c 18 5d 42 7f 8c c2 fb 88 : d5 d7 23 52 17 5e 9c 31 30 e3 6a 8e f1 e4 85 b9 : 38 10 bf 97 2a 01 12 b5 0a 8b 6e 5c aa 01 01 db : c6 4b 1f 83 2c 79 3a 03 67 a2 59 25 24 3a 42 54 : fc a5 c7 53 5b a5 d0 56 89 9b a4 b6 f2 1d 66 28 : e9 db 35 23 d8 31 1b 37 88 fc fc c1 0f 09 58 e5 : 32 0a b3 71 e9 2a 56 ec 92 74 ab ad f4 27 e4 77 : }
Первый блоб у нас секретная часть ключа, второй блоб непонятно (рабочая точка кривой?, секретная?),
последний блоб - публичный ключ. Его видно в сертификатах и легко вытащить программно.
Итого наш "секрет" имеет размер 64 байта (512 бит).
Будем пробовать его вытаскивать certutil.Вот что мы видим для криптопро PFX:
{ version: 3, authSafe: { contentType: "data", content: [ 0x30, 0x82, 0x04, 0xa3, 0x30, 0x82, 0x01, 0xca, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x01, 0xbb, 0x04, 0x82, 0x01, 0xb7, 0x30, 0x82, 0x01, 0xb3, 0x30, 0x82, 0x01, 0xaf, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x81, 0xd4, 0x30, 0x81, 0xd1, 0x30, 0x1c, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0e, 0x04, 0x08, 0xf1, 0xc8, 0xaf, 0xf2, 0x7f, 0xbd, 0x6a, 0xe1, 0x02, 0x02, 0x07, 0xd0, 0x04, 0x81, 0xb0, 0xc2, 0x1c, 0x25, 0xa3, 0xe0, 0x75, 0xca, 0xf4, 0xab, 0xf5, 0xc6, 0xe9, 0x34, 0xb9, 0x33, 0x30, 0xfd, 0xdf, 0xca, 0xc0, 0x45, 0x18, 0x81, 0x4e, 0x50, 0xcf, 0xa6, 0xe2, 0x73, 0xf6, 0x2b, 0xf3, 0xd8, 0x42, 0xc5, 0x06, 0xef, 0xbd, 0xcc, 0x4a, 0x95, 0xbe, 0xb9, 0x9d, 0x40, 0xeb, 0xb5, 0x5b, 0xed, 0x4e, 0xd5, 0xa0, 0xbc, 0x0a, 0xc0, 0x60, 0x7e, 0xc2, 0xaa, 0x8f, 0xf3, 0x7b, 0x2b, 0xd9, 0x1b, 0xc7, 0x53, 0x8d, 0x33, 0x06, 0x7a, 0x75, 0x27, 0xe2, 0xf1, 0xee, 0xb9, 0xb9, 0xfe, 0xc7, 0xb1, 0xea, 0x15, 0x38, 0xc5, 0xc2, 0x8a, 0xf3, 0xad, 0x07, 0x18, 0x93, 0xad, 0x99, 0x4f, 0x1d, 0xb6, 0xe2, 0x25, 0x54, 0x91, 0xf6, 0x0e, 0x34, 0xed, 0xea, 0x38, 0x6e, 0x17, 0xdd, 0x96, 0x01, 0xec, 0x0e, 0x36, 0xa4, 0xac, 0xf5, 0xbe, 0xd1, 0x08, 0x1b, 0xef, 0x95, 0x8f, 0x47, 0x93, 0x1d, 0xdd, 0xc1, 0x88, 0x4f, 0x58, 0xa6, 0x34, 0xef, 0x17, 0xf5, 0xb4, 0x82, 0x89, 0x83, 0xf0, 0xa7, 0xb0, 0xff, 0x93, 0x08, 0x97, 0x94, 0x71, 0xf5, 0x2a, 0x9d, 0x22, 0x0b, 0x44, 0x51, 0x60, 0xf0, 0x1e, 0xf0, 0x8d, 0x92, 0x2b, 0x4c, 0xb6, 0x25, 0x66, 0x1a, 0x23, 0xf1, 0x8a, 0x9f, 0xb8, 0x50, 0x31, 0x81, 0xc8, 0x30, 0x13, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x06, 0x04, 0x04, 0x01, 0x00, 0x00, 0x00, 0x30, 0x19, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x14, 0x31, 0x0c, 0x1e, 0x0a, 0x00, 0x54, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x31, 0x30, 0x81, 0x95, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x11, 0x01, 0x31, 0x81, 0x87, 0x1e, 0x81, 0x84, 0x00, 0x43, 0x00, 0x72, 0x00, 0x79, 0x00, 0x70, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x2d, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x20, 0x00, 0x47, 0x00, 0x4f, 0x00, 0x53, 0x00, 0x54, 0x00, 0x20, 0x00, 0x52, 0x00, 0x20, 0x00, 0x33, 0x00, 0x34, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x30, 0x00, 0x2d, 0x00, 0x32, 0x00, 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x20, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x20, 0x00, 0x43, 0x00, 0x72, 0x00, 0x79, 0x00, 0x70, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x67, 0x00, 0x72, 0x00, 0x61, 0x00, 0x70, 0x00, 0x68, 0x00, 0x69, 0x00, 0x63, 0x00, 0x20, 0x00, 0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, 0x65, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x76, 0x00, 0x69, 0x00, 0x64, 0x00, 0x65, 0x00, 0x72, 0x30, 0x82, 0x02, 0xd1, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x02, 0xc2, 0x04, 0x82, 0x02, 0xbe, 0x30, 0x82, 0x02, 0xba, 0x30, 0x82, 0x02, 0xb6, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x03, 0xa0, 0x82, 0x02, 0x8e, 0x30, 0x82, 0x02, 0x8a, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x16, 0x01, 0xa0, 0x82, 0x02, 0x7a, 0x04, 0x82, 0x02, 0x76, 0x30, 0x82, 0x02, 0x72, 0x30, 0x82, 0x01, 0xde, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x18, 0x9e, 0x42, 0x75, 0xf7, 0xe9, 0x7f, 0x0b, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x01, 0x03, 0x03, 0x30, 0x22, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x52, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x1e, 0x0a, 0x04, 0x42, 0x04, 0x35, 0x04, 0x41, 0x04, 0x42, 0x00, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x34, 0x30, 0x36, 0x31, 0x30, 0x31, 0x30, 0x32, 0x36, 0x5a, 0x17, 0x0d, 0x31, 0x38, 0x30, 0x34, 0x30, 0x36, 0x31, 0x30, 0x31, 0x30, 0x32, 0x36, 0x5a, 0x30, 0x22, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x52, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x1e, 0x0a, 0x04, 0x42, 0x04, 0x35, 0x04, 0x41, 0x04, 0x42, 0x00, 0x31, 0x30, 0x81, 0xaa, 0x30, 0x21, 0x06, 0x08, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x01, 0x01, 0x02, 0x30, 0x15, 0x06, 0x09, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x02, 0x01, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x01, 0x02, 0x03, 0x03, 0x81, 0x84, 0x00, 0x04, 0x81, 0x80, 0x5a, 0xda, 0x7d, 0x4e, 0x4d, 0x7a, 0x24, 0x6c, 0x12, 0x83, 0xb0, 0x57, 0x9f, 0xb7, 0x9f, 0xca, 0xb8, 0x4b, 0xb0, 0xee, 0x64, 0x60, 0x41, 0x5c, 0x18, 0x5d, 0x42, 0x7f, 0x8c, 0xc2, 0xfb, 0x88, 0xd5, 0xd7, 0x23, 0x52, 0x17, 0x5e, 0x9c, 0x31, 0x30, 0xe3, 0x6a, 0x8e, 0xf1, 0xe4, 0x85, 0xb9, 0x38, 0x10, 0xbf, 0x97, 0x2a, 0x01, 0x12, 0xb5, 0x0a, 0x8b, 0x6e, 0x5c, 0xaa, 0x01, 0x01, 0xdb, 0xc6, 0x4b, 0x1f, 0x83, 0x2c, 0x79, 0x3a, 0x03, 0x67, 0xa2, 0x59, 0x25, 0x24, 0x3a, 0x42, 0x54, 0xfc, 0xa5, 0xc7, 0x53, 0x5b, 0xa5, 0xd0, 0x56, 0x89, 0x9b, 0xa4, 0xb6, 0xf2, 0x1d, 0x66, 0x28, 0xe9, 0xdb, 0x35, 0x23, 0xd8, 0x31, 0x1b, 0x37, 0x88, 0xfc, 0xfc, 0xc1, 0x0f, 0x09, 0x58, 0xe5, 0x32, 0x0a, 0xb3, 0x71, 0xe9, 0x2a, 0x56, 0xec, 0x92, 0x74, 0xab, 0xad, 0xf4, 0x27, 0xe4, 0x77, 0xa3, 0x81, 0xab, 0x30, 0x81, 0xa8, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0xde, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x04, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xff, 0x31, 0x79, 0xbb, 0xc3, 0xb0, 0xc7, 0x48, 0x3d, 0xac, 0x64, 0x38, 0xce, 0x06, 0x56, 0x55, 0xc9, 0x81, 0xc7, 0x88, 0x30, 0x47, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x40, 0x30, 0x3e, 0x80, 0x14, 0xff, 0x31, 0x79, 0xbb, 0xc3, 0xb0, 0xc7, 0x48, 0x3d, 0xac, 0x64, 0x38, 0xce, 0x06, 0x56, 0x55, 0xc9, 0x81, 0xc7, 0x88, 0xa1, 0x26, 0xa4, 0x24, 0x30, 0x22, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x52, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x1e, 0x0a, 0x04, 0x42, 0x04, 0x35, 0x04, 0x41, 0x04, 0x42, 0x00, 0x31, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x01, 0x03, 0x03, 0x03, 0x81, 0x81, 0x00, 0x5a, 0x9b, 0x83, 0x59, 0x72, 0x6b, 0x99, 0xcb, 0xfd, 0x76, 0x62, 0xea, 0xfd, 0x90, 0xf1, 0xd5, 0x30, 0x73, 0x77, 0x71, 0x46, 0xd6, 0xeb, 0x57, 0x39, 0xbc, 0x58, 0x61, 0x9e, 0x4b, 0x2c, 0x80, 0xf9, 0xca, 0xe6, 0x62, 0xef, 0x36, 0xa4, 0x9e, 0xd0, 0x00, 0xb7, 0xd5, 0xcf, 0xf0, 0xed, 0x23, 0x09, 0xc1, 0x93, 0xf8, 0xde, 0x85, 0x71, 0x23, 0x94, 0xc3, 0xb2, 0xe4, 0x88, 0x24, 0xa4, 0x36, 0x68, 0x64, 0x17, 0x0e, 0x31, 0x1b, 0xae, 0x16, 0x4a, 0x24, 0xad, 0x98, 0xda, 0x12, 0x53, 0x06, 0x97, 0xab, 0x46, 0x61, 0x28, 0xe9, 0xcf, 0x3d, 0x4e, 0xfd, 0xdd, 0x3f, 0x55, 0xbb, 0x96, 0x43, 0xcf, 0x01, 0x8c, 0x61, 0x4f, 0xbb, 0xd7, 0x67, 0x25, 0xb2, 0x46, 0xd4, 0x00, 0xbb, 0x95, 0x64, 0x5e, 0xf2, 0x40, 0xb0, 0x23, 0xc4, 0xc3, 0xc6, 0xd5, 0x14, 0xd2, 0x48, 0xbb, 0xa2, 0xde, 0x12, 0x31, 0x15, 0x30, 0x13, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x06, 0x04, 0x04, 0x01, 0x00, 0x00, 0x00 ] }, macData: { mac: { digestAlgorithm: { name: "SHA-1", id: "sha1" }, digest: [ 0xa8, 0xc4, 0xab, 0x31, 0x0c, 0xa5, 0x5c, 0x38, 0xda, 0xd4, 0xf6, 0x9e, 0xb7, 0x8a, 0x05, 0xc6, 0xe5, 0xc8, 0xbd, 0x41 ] }, macSalt: [ 0xaa, 0xbf, 0x9e, 0xa1, 0xb4, 0x1b, 0x04, 0x44, 0x02, 0x34, 0x2e, 0x8f, 0xc7, 0xa3, 0x99, 0x75, 0xfc, 0x79, 0xef, 0x91 ], iterations: 2000 } }
Версия контейнера 3, затем идёт блоб данных, затем секция HMAC контрольной суммы.
КС на алгоритме SHA-1, видим соль, количество итераций, и саму сумму.
Чуток исследований и получаем следующий алгоритм проверки суммы:
use v5.10;
use Digest::SHA qw/hmac_sha1 sha1/;
use Encode qw/encode/;
use utf8;
sub unhex($){my $d=shift;$d=~s/[^0-9a-fA-F]//g;pack'H*',$d}
sub tohex($){my $d=uc unpack 'H*',shift;$d=~s/../$& /g;chop $d;$d}
$salt=unhex '70 FA F5 FD AB EE 39 0F 1F CE 34 B8 3F 87 17 A2 D2 11 25 75';
$rounds=2000; $ver=3; $pass='1234Ё'; $pass=encode('UCS-2BE', $pass."\0"); $data=((pack'C',$ver) x 64) . substr($salt x 4, 0, 64) . substr($pass x 16, 0, 64); say "ToHash:",tohex $data; for (my $i=0;$i<$rounds;$i++){$data=sha1($data)} say "Hmac_Key:",uc unpack'H*', $data; $crc=unhex 'a8, 0xc4, 0xab, 0x31, 0x0c, 0xa5, 0x5c, 0x38, 0xda, 0xd4, 0xf6, 0x9e, 0xb7, 0x8a, 0x05, 0xc6, 0xe5, 0xc8, 0xbd, 0x41'; $blob=unhex ''; my $crc1=hmac_sha1($blob, $data); say "Data is: ".($crc eq $crc1? "Valid": "Invalid");
Но это пока не проблема.
Проблема внутри блоба. Посмотрим его отдельно.
http://gostcrypto.com/tool-asn1.htmlOBJECT IDENTIFIER pkcs8ShroudedKeyBag (1.2.840.113549.1.12.10.1.2) [0] { SEQUENCE { SEQUENCE { OBJECT IDENTIFIER pbeWithSHAAnd3-KeyTripleDES-CBC (1.2.840.113549.1.12.1.3) SEQUENCE { OCTET STRING f1 c8 af f2 7f bd 6a e1 INTEGER 2000 } } OCTET STRING : c2 1c 25 a3 e0 75 ca f4 ab f5 c6 e9 34 b9 33 30 : fd df ca c0 45 18 81 4e 50 cf a6 e2 73 f6 2b f3 : d8 42 c5 06 ef bd cc 4a 95 be b9 9d 40 eb b5 5b : ed 4e d5 a0 bc 0a c0 60 7e c2 aa 8f f3 7b 2b d9 : 1b c7 53 8d 33 06 7a 75 27 e2 f1 ee b9 b9 fe c7 : b1 ea 15 38 c5 c2 8a f3 ad 07 18 93 ad 99 4f 1d : b6 e2 25 54 91 f6 0e 34 ed ea 38 6e 17 dd 96 01 : ec 0e 36 a4 ac f5 be d1 08 1b ef 95 8f 47 93 1d : dd c1 88 4f 58 a6 34 ef 17 f5 b4 82 89 83 f0 a7 : b0 ff 93 08 97 94 71 f5 2a 9d 22 0b 44 51 60 f0 : 1e f0 8d 92 2b 4c b6 25 66 1a 23 f1 8a 9f b8 50 } }
Иногда экспортируется вот в таком формате: pbeWithSHAAnd3-KeyTripleDES-CBC
Но чаще вот в этом:
65 06 11: OBJECT IDENTIFIER pkcs8ShroudedKeyBag (1.2.840.113549.1.12.10.1.2) 78 a0 219: [0] { 81 30 216: 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 : d0 c5 eb df 99 b7 b7 82 7c e0 b1 a6 7f a7 57 10 118 02 2: INTEGER 2000 : } : } 122 04 175: OCTET STRING, encapsulates { 125 82 5: [2] : d5 12 ea 73 dc : } : }
pbeUnknownGost: OID=1.2.840.113549.1.12.1.80
Суть алгоритма в следующем. Генерируется 16-байтная соль.
В данном случае SALT=d0 c5 eb df 99 b7 b7 82 7c e0 b1 a6 7f a7 57 10
Количество итераций ROUNDS=2000=0x7C0
Берётся пароль, кодировка UCS-2LE.
use Digest::GOST::CryptoPro qw(gost);
$salt="\x11" x 16;$rounds=0x7D0;$pass='1';$pass=encode('UCS-2LE', $pass); $key=$pass;for (my $i=1;$i<=$rounds;$i++){$key=gost($key.$salt.pack('n',$i))}
Полученный ключ используется как
1) ключ шифрования для экспорта приватного из криптопровайдера и
2) ключ шифрования блоба от криптопровайдера алгоритмом гост89.
Encrypt_Gost89(D, IV=>"\x11" x 16, Key=>"\x22" x 32);
То есть для расшифровки надо сначала расшифровать блоб симметричным алгоритмом
Гост89, KEY=$key, IV=$salt, MODE=CFB
А затем что-то сделать с ключом, чтобы расшифровать транспортную кодировку
криптопровайдера ALG_XXX_EXPORT.
Да, да. Ключ дважды зашифрован - от провайдера идёт зашифрованный секретный ключ,
благо "пароль" мы уже знаем, а потом его ещё раз шифрует certutil.
Алгоритм транспортного шифрования для "новых" ключей (после 2012 года)
CALG_PRO12_EXPORT 0x6621.
Старые Гост89 ключи и сеансовые ключи могут шифроваться CALG_SIMPLE_EXPORT 0x6620.
Ключи до 2012 года также могут быть зашифрованы CALG_PRO_EXPORT 0x661F.
Посмотрим, что у нас есть.
После расшифровки контейнера получаем такую структуру:
Try1: 07 20 00 00 42 AA 00 00 4D 41 47 31 40 00 00 00 30 81 85 30 7D 04 08[B6 4C 7D F7 03 3B FB A1] 30 48 04 40[53 43 86 06 ED 3E 98 B2 11 46 1C 3A E3 60 72 42 B2 34 5C 7F 3A FB D4 E8 45 BF 51 92 34 21 66 BE 27 81 B7 71 25 C3 A1 03 B0 48 23 02 2F 99 A7 D2 A7 A0 76 EE 9C ED FE 1A A1 F5 A9 EC 26 62 AB 58] 04 04[24 CE 0F 03]A0 27 03 02 05 A0 A0 21 06 08 2A 85 03 07 01 01 06 02 30 15 06 09 2A 85 03 07 01 02 01 02 01 06 08 2A 85 03 07 01 01 02 03 04 04[B5 13 07 5C] SALT=B6 4C 7D F7 03 3B FB A1 DATA=53 43 86 06 ED 3E 98 B2 11 46 1C 3A E3 60 72 42 B2 34 5C 7F 3A FB D4 E8 45 BF 51 92 34 21 66 BE 27 81 B7 71 25 C3 A1 03 B0 48 23 02 2F 99 A7 D2 A7 A0 76 EE 9C ED FE 1A A1 F5 A9 EC 26 62 AB 58 CRC1=24 CE 0F 03
CRC2=B5 13 07 5C Try2: 07 20 00 00 42 AA 00 00 4D 41 47 31 40 00 00 00 30 81 85 30 7D 04 08[B0 FF 35 17 58 46 51 5D] 30 48 04 40[7E 72 A9 41 D9 83 52 F2 FE 93 4C 68 3C 55 0B 2F E8 34 93 3C 54 2F 9C 54 7D 6B AF C5 66 D5 20 7F A1 EC 44 6E 1D 2F C6 FA 4E FA A9 C3 A4 A8 E5 5D B2 62 3E E1 60 9B 8D 64 83 EC 46 6B 82 24 B5 8F] 04 04[28 33 16 9D]A0 27 03 02 05 A0 A0 21 06 08 2A 85 03 07 01 01 06 02 30 15 06 09 2A 85 03 07 01 02 01 02 01 06 08 2A 85 03 07 01 01 02 03 04 04[2E 89 9F 22]
Вначале структуры видны 16 байт заголовка, после чего идёт ASN.1
Опять видим соль (8 байт), данные (64 байта) и пара 4-байтных чисел (имитовставки или кс).
В заголовке видны цифры:
0x2007 - видимо сигнатура заголовка и заодно год создания стандарта структуры :)
CALG_DH_GR3410_2012_512_SF = 0AA42h ; Идентификатор алгоритма обмена ключей по Диффи-Хеллману на базе закрытого ключа пользователя.
Открытый ключ получается по ГОСТ Р 34.10 2012 (512 бит).
Открытый ключ получается по ГОСТ Р 34.10 2012 (512 бит).
GR3410_1_MAGIC = 3147414Dh ; Признак ключей ГОСТ Р 34.10-94 и ГОСТ Р 34.10-2001.
040h = размер секретного ключа (64 байта).
Внутри ASN.1 нас дополнительно посылают на OID:
1.2.643.7.1.1.6.2
1.2.643.7.1.2.1.2.1
1.2.643.7.1.1.2.3
to be continued...
3 комментария:
Привет. Столкнулся с тем же самым. Криптопро, не стесняясь, использует никому не известный 1.2.840.113549.1.12.1.80 и никто не может прочитать контейнер, ломаясь на неизвестном алгоритме.
Пока не покупал эту штуку, которая от "Лисси" (?), но интересно, а у них какой OID на том месте, где КП пишет 1.2.840.113549.1.12.1.80?
я доковырял транспортное шифрование и проверку целостности контейнера с этим 1.80 - а дальше всё упёрлось в экспортное шифрование приватного ключа.
Т.е можно рассматривать оид контейнера "вскрытым" (на perl сделал проги проверки-расчёта кс и расшифровки контейнера).
Лисси на рубоарде можно найти. Там и п12экспорт "полный" и фокс-ца 2.0.
Они в п12 пихают почти то же самое - только кс у них гостовская а не sha и алгоритм деривиации ключа от пароля чуть другой. Тоже вроде вскрылось нормально.
Загвоздка оказалась в экспортном шифровании ключа. И лисы и прошники получают ключ одинаково (а главное экспортируют-импортируют одно и то же).
создаётся параметр шифрования на основе пользовательского пароля - и передаётся в драйвер с параметром crypt_export (их там штуки три кодов экспортных шифров - для новых ключей обязателен новый гост - это требование сертификации). Так вот саму генерацию и передачу ключа в драйвер я вижу - а на выходе уже зашифрованный контейнер ключа. Что там в драйвере творится у меня дабаггер не видит (x64 debugger - он юзерлевел). А декомпилёный драйвер с ООП и таблицами виртуальных методов - там без реальной отладки даже куда лезть непонятно.
Т.е. параметры приватного ключа из расшифрованного транспортного контейнера не могу получить (чтобы отдать тому же openssl) - но могу передать блоб в драйвер кпро для дальнейшего импорта. Научиться бы раскрывать этот crypt_export - там 100% банальный гост, только с солением и многопроходной обработкой ключа (как и транспортное шифрование).
Gimly, вот есть такие данные:
'CP-01': {
title: 'Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider',
signature: algorithms['id-GostR3411-94-with-GostR3410-2001'],
publicKey: {id: 'id-GostR3410-2001', name: 'GOST R 34.10-2001', namedCurve: 'X-256-A'},
privateKey: {id: 'id-GostR3410-2001DH', name: 'GOST R 34.10-2001-DH', namedCurve: 'X-256-A'},
digest: {id: 'id-GostR3411-94', name: 'GOST R 34.11-94', sBox: 'D-A'},
wrapping: {id: 'id-Gost28147-89-CryptoPro-KeyWrap', name: 'GOST 28147-89-CPKW', sBox: 'E-A'},
hmac: algorithms['id-HMACGostR3411-94'],
agreement: algorithms['id-GostR3410-2001-CryptoPro-ESDH'],
encryption: {id: 'id-Gost28147-89', name: 'GOST 28147-89-CFB-CPKM', sBox: 'E-A'},
derivation: {id: 'PBKDF2', name: 'GOST R 34.11-94-PBKDF2', iterations: 2000}
},
Есть вероятность, что поля encryption и derivation используются уже для экспортного шифрования.
Т.е. почти то же, что и в первой, только pde типа PBKDF2 и для GOST 28147-89 используется sbox E-A.
Вопрос в том, какая соль и какой пароль использовать.
Отправить комментарий