06.06.2004 17:41:32Экспорт сессионного ключа по схеме DH Ответов: 12
Вадим
Насколько я понимаю, для этого нужно два сертификата: сертификат отправителя (= private key) и сертификат получателя (= public key). То есть, ключ получателя импортируется на ключе отправителя, а затем используется для экспорта сессионного ключа.

Но на принимающей стороне нам известен только сертификат получателя, использованный для экспорта (информация о нем лежит в PKCS7 RecipientInfo), однако ничего неизвестно о сертификате отправителя! Как же быть?

Кроме того, в CAPICOM в объект EnvelopeData передается только сертификат получателя, откуда же Ваш код (в cpadvai.dll) берет ключ отправителя? Прав ли я, что Вы просто используете CryptGetUserKey для получения ключа _по умолчанию_ для текущего пользователя, а если такового нет – он генерируется на лету? Не кажется ли Вам, что такое неконтролируемое поведение немного некорректно? (Я бы, к примеру, предпочел, чтобы приложение _спросило_ меня какой именно ключ использовать для обмена.)

Спасибо.
 
Ответы:
07.06.2004 15:12:34Вадим
Прошу прощения за этот пинг, но все-таки хотелось бы получить ответ на вопрос...
07.06.2004 22:49:55xyz
Используется эфемеральный алгоритм DH - эфемерный ключ отправителя лежит в сообщении, и cpadvai здесь не причем. Почитайте повнимательнее PKCS7.
08.06.2004 11:39:04Вадим
Из описания к СКЗИ CryptoPro CSP 2.0 (csp_2_0.chm):

Обычно для согласования (экспорта/импорта) сессионного ключа применяют алгоритм Диффи-Хеллмана. В этом случае ключ парной связи (ключ экспорта/импорта сессионного ключа) порождается операцией импорта открытого ключа получателя (отправителя) на ключевой паре отправителя (получателя).

CPExportKey: Для экспорта сессионного ключа следует выполнить следующие шаги:

Импорт блоба открытого ключа получателя на своей ключевой паре;
Экспорт сессионого ключа на ключе парной связи:
...
CPGetUserKey(hProv, AT_KEYEXCHANGE, &hUserKey);
...
CPGenKey(hProv, CALG_G28147, CRYPT_EXPORTABLE, &hSessionKey);
...
CPImportKey(hProv, pbRecipentPublicKey, cbRecipentPublicKey, hUserKey, 0, &hExchKey);
CPExportKey(hProv, hSessionKey, hExchKey, SIMPLEBLOB, 0, pbSessionKeyForRecipient, &cbSessionKeyForRecipient);
...

CPImportKey: Для импорта сессионного ключа следует выполнить следующие шаги:

Импорт блоба открытого ключа отправителя на своей ключевой паре;
Импорт сессионого ключа на ключе парной связи:
...
CPGetUserKey(hProv, AT_KEYEXCHANGE, &hUserKey);
...
CPImportKey(hProv, pbSenderPublicKey, cbSenderPublicKey, hUserKey, 0, &hExchKey);
CPImportKey(hProv, pbSessionKeyFromSender, &cbSessionKeyFromSender, hExchKey, 0, &hSessionKey);
...
08.06.2004 11:43:41Вадим
Собственно смущает фраза "импорт блоба открытого ключа отправителя на своей ключевой паре" - как видно эфимерный ключ здесь не причем(?), ведь здесь явно импортится ключ отправителя.

Поправьте меня, plz, если я чего-то не понимаю (а судя по всему это так :)
08.06.2004 11:52:42Вадим
Кроме того, для получения ключа обмена используется вызов CPGetUserKey(hProv, AT_KEYEXCHANGE, &hUserKey) - какой контейнер используется в данном случае? Вспомним еще разок: CAPICOM не позволяет выбрать сертификат/ключ _отправителя_, могу лишь предположить, что в cpadvai.dll (а эта DLL здесь именно что причем, ведь код собирающий PKCS7 EnvelopedData на ГОСТ’е находится именно в ней) используется дефолтный контейнер текущего пользователя (лень мне отлаживаться, чтобы установить это точно).
08.06.2004 12:42:12Вадим
Тьфу, не cpadvai, конечно, а cpcrypt.
08.06.2004 17:01:25Василий
Если используете CryptoAPI - можно экспортировать как на эфемеральном, так и на реальном ключе Диффи-Хеллмана. В последнем случае ключ DH получается из своего закрытого и чужого открытого ключа.
Если используете CAPICOM - экспортировать получится только на эфемеральном ключе DH.
08.06.2004 17:14:33Вадим
Угу, начинаю понимать. В таком случае меня интересует именно случай эфемерного ключа DH. Не могли бы Вы указать на пример кода, в котором сессионный ключ выгружается подобным образом? (в примере из sample2_0.zip я нашел только случай реального ключа), меня _особенно_ интересует ручное создание структуры RecipientInfo.

P.S.: А с точки зрения криптостойкости, есть ли разница между двумя этими алгоритмами?
08.06.2004 19:01:25Григорий Чудов
> Прав ли я, что Вы просто используете CryptGetUserKey для получения ключа _по умолчанию_ для текущего пользователя, а если такового нет – он генерируется на лету?

Нет. Эфемерный ключ отправителя передаётся вместе с зашифрованным сессионным ключем в поле RecipientInfo.EncryptedKey.

Подробности смотрите в http://www.ietf.org/internet-drafts/draft-ietf-smime-gost-02.txt
08.06.2004 21:25:59Вадим
Это понятно.

Я говорил про _экспорт_ сессионного ключа. В любом случае (что эфемерный, что реальный ключ) требуется открытый ключ получателя и _секретный ключ отправителя_.
С получателем все ясно, в CAPICOM передается сертификат получателя, а вот с ключом отправителя не все ясно:
CAPICOM не позволяет выбрать сертификат/ключ отправителя, собственно отсюда и мой вопрос.
08.06.2004 21:31:37Вадим
2 xyz:
PKCS7 здесь абсолютно ни при чем. Максимум, что можно упомянуть, это PKCS3, но там информации минимум (про алгоритм с эфемерным ключом я там не нашел ничего)
15.06.2004 16:09:20Чудов Григорий Сергеевич
> Я говорил про _экспорт_ сессионного ключа. В любом случае (что эфемерный, что реальный ключ) требуется открытый ключ получателя и _секретный ключ отправителя_.

Как уже было сказано, схема Fixed DH не поддерживается. То есть, всегда используется эфемеральный (то есть, временный, уникальный для сообщения) ключ отправителя.

Никакого контейнера по умолчанию не используется.