Ключевое слово в защите информации
ключевое слово
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход. Новые регистрации запрещены.

Уведомление

Icon
Error

2 Страницы12>
Опции
К последнему сообщению К первому непрочитанному
Offline Андрей Куликов  
#1 Оставлено : 9 января 2011 г. 6:51:05(UTC)
Андрей Куликов

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 17.10.2010(UTC)
Сообщений: 147
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 2 раз
Поблагодарили: 10 раз в 9 постах
Пытаюсь получить TSL premaster_secret в чистом виде на стороне сервера.

Дано:
HCRYPTKEY our_priv; // в контейнере
HCRYPTKEY peer_pub; // прислал клиент, мы его импортировали.
unsigned char wrapped_key[44]; // прислал клиент

Первые 8 байт wrapped_key используются как UKM.

Надо: получить 32 байта premaster_secret.
Это ключ 28147. Так что можно и его дескриптор - потом экспортирую и вытащу premaster_secret в чистом виде.


Читаю это: http://cryptopro.ru/foru...t.aspx?g=posts&t=135
Там про сторону клиента. Как обратить это для стороны сервера - не понятно.

Ну, создадим CALG_TLS1_MASTER
Код:
HCRYPTKEY kek = 0; // Key Encryption Key
CryptGenKey(hProv, CALG_TLS1_MASTER, CRYPT_EXPORTABLE, &kek)


Кому устанавливать UKM? kek или peer_pub?

На каком ключе импортировать wrapped_key?
Если на kek - то откуда импорт возьмет peer_pub?
Если на peer_pub - то зачем нужен ключ kek/CALG_TLS1_MASTER?

Какой тип блоба указывать при импорте? SIMPLEBLOB?
Но wrapped_key - это не CRYPT_SIMPLEBLOB. Там хедера нету и ASN1 параметров алгоритма. Хедер ручками формировать?

Что еще надо учесть?

Отредактировано пользователем 9 января 2011 г. 17:26:02(UTC)  | Причина: Не указана

Offline Максим Коллегин  
#2 Оставлено : 9 января 2011 г. 19:38:18(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,457
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 39 раз
Поблагодарили: 750 раз в 645 постах
Пришлите или выложите свой код - попробуем поправить.
Знания в базе знаний, поддержка в центре поддержки
Offline Андрей Куликов  
#3 Оставлено : 9 января 2011 г. 22:32:58(UTC)
Андрей Куликов

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 17.10.2010(UTC)
Сообщений: 147
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 2 раз
Поблагодарили: 10 раз в 9 постах
Праздники, воскресение, вечер. Люди пишут код...

ukm - из GostR3410-TransportParameters из RFC 4490
pbClientPublicKey - это ephemeralPublicKey из RFC 4490 (клиент сертификата не шлет (пока, по крайней мере...))
wrapped_key - это Gost28147-89-EncryptedKey из RFC 4490 с присоедененным сверху ukm (БЕЗ maskKey). Что соответствует CryptoPro Key Wrap 6.3 RFC 4357.


Код:

unsigned char wrapped_key[44]; // Из структуры транспорта ключа клиента.
// Первые 8 байт - это ukm

HCRYPTKEY our_priv;
CryptGetUserKey(hProv, AT_KEYEXCHANGE, &our_priv);

HCRYPTKEY peer_pub;
CryptImportKey(hProv, pbClientPublicKey, cbClientPublicKey, 0, 0, &peer_pub);

ALG_ID ke_alg = CALG_PRO_EXPORT;
CryptSetKeyParam (hProv, peer_pub, KP_ALGID, (LPBYTE)&ke_alg, 0 );

CryptSetKeyParam (hProv, peer_pub, KP_SV, ukm, 0);

HCRYPTKEY premaster_key;
// Тут что-то не то...
CryptImportKey(hProv, wrapped_key, 44, CRYPT_EXPORTABLE, &premaster_key);


Посмотрел еще раз сюда:
http://cryptopro.ru/foru...t.aspx?g=posts&t=135
Там в клиенте открытый ключ сервера импортируется с использованием клиентского AT_KEYEXCHANGE.
Может, вопреки документации, и нам стоит открытый ключ клиента импортировать на нашем ключе обмена our_priv?
И там у них что-то замкнет, и импорт премастера поймет откуда ему брать открытый ключ клиента?

Или, может быть я слишком всё усложняю, и можно какую-нибуть структуру из rfc4490 (типа GostR3410-KeyTransport) импортировать одним махом?

Отредактировано пользователем 9 января 2011 г. 22:40:19(UTC)  | Причина: Не указана

Offline Максим Коллегин  
#4 Оставлено : 10 января 2011 г. 0:10:09(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,457
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 39 раз
Поблагодарили: 750 раз в 645 постах
код выше - вообще ни о чем.
Где согласование ключа обмена (импорт блоба открытого ключа на закрытый сервера)?
На этот ключ потом устанавливаем CALG_SIMPLE_EXPORT.
Потом вручную собираем SIMPLEBLOB. Такой: hkeyblob->BlobHeader.aiKeyAlg = CALG_TLS1_MASTER;
Ну и импортируем ключ.
Как всегда вопрос - зачем?
Знания в базе знаний, поддержка в центре поддержки
Offline Андрей Куликов  
#5 Оставлено : 11 января 2011 г. 0:27:05(UTC)
Андрей Куликов

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 17.10.2010(UTC)
Сообщений: 147
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 2 раз
Поблагодарили: 10 раз в 9 постах
УРА! Заработало!! Импортируется!

Спасибо огромное!

А зачем... Да побольше серверных лицензий CSP продать, наверное...

Отредактировано пользователем 11 января 2011 г. 0:45:49(UTC)  | Причина: Не указана

Offline Максим Коллегин  
#6 Оставлено : 11 января 2011 г. 2:15:38(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,457
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 39 раз
Поблагодарили: 750 раз в 645 постах
Отлично. А можно в студию порядок вызовов для потомков - а я в FAQ помещу.
Знания в базе знаний, поддержка в центре поддержки
Offline Андрей Куликов  
#7 Оставлено : 11 января 2011 г. 2:40:12(UTC)
Андрей Куликов

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 17.10.2010(UTC)
Сообщений: 147
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 2 раз
Поблагодарили: 10 раз в 9 постах
Тут еще такая засада обнаружилась - импортированный таким образом ключ потом экспортироваться не хочет.

Импортируется из SIMPLEBLOB с флагом CRYPT_EXPORTABLE.
При последующих попытках экспортировать его в другой SIMPLEBLOB CryptExportKey возвращает NTE_BAD_KEY_STATE.

Ключ экспорта создается так:
CryptGenKey(hProvider, CALG_G28147, CRYPT_EXPORTABLE, &export_key) // Без CRYPT_EXPORTABLE тот же эффект.
потом:
DWORD dparam = CALG_SIMPLE_EXPORT;
CryptSetKeyParam(export_key, KP_ALGID, (BYTE *)&dparam, 0)

Потом экспортирует импортированный премастер:
CryptExportKey(premaster, export_key, SIMPLEBLOB, 0, (LPBYTE)keyBlob, &keyBlobLen)

Получаем NTE_BAD_KEY_STATE.


Если просто сгенерировать ключ CALG_G28147, то он таким образом прекрасно экспортируется.
А импортированный премастер - нет.

Почему это может происходить?
Может потомков еще рано радовать? :-((
Offline Максим Коллегин  
#8 Оставлено : 11 января 2011 г. 2:58:30(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,457
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 39 раз
Поблагодарили: 750 раз в 645 постах
мда. Ну этого никто и не обещал. Можно для потомков все ручками родить. Перенесем беседу в email
Знания в базе знаний, поддержка в центре поддержки
Offline Андрей Куликов  
#9 Оставлено : 12 января 2011 г. 23:13:11(UTC)
Андрей Куликов

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 17.10.2010(UTC)
Сообщений: 147
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 2 раз
Поблагодарили: 10 раз в 9 постах
Для потомков:


Получаем premaster_secret TLS средствами CryptoAPI на стороне СЕРВЕРА.
Для случая если клиентский сертификат не используется.

1. Изучаем RFC 4490, особенно раздел 4.2.1
http://tools.ietf.org/html/rfc4490

2. Парсим структуру GostR3410-KeyTransport из RFC 4490, которую нам прислал клиент.

3. Собираем CRYPT_PUBLICKEYBLOB из присланного клиентом открытого ключа GostR3410-KeyTransport::ephemeralPublicKey и параметров GostR3410-KeyTransport::transportParameters::encryptionParamSet

Код:
    // Конкретное содержимое структуры зависит от NID encryptionParamSet.
	static const BYTE default_params_3410_2001[] = { 0x30, 0x12, 0x06, 0x07,
                                                 0x2A, 0x85, 0x03, 0x02,
                                                 0x02, 0x24, 0x00, 0x06,
                                                 0x07, 0x2A, 0x85, 0x03,
                                                 0x02, 0x02, 0x1E, 0x01
                                                };

	const int RAW_PUB_OFFSET = (sizeof(CRYPT_PUBKEY_INFO_HEADER) +  GOST3410_PUBKEYPARAM_SIZE);

	CRYPT_PUBLICKEYBLOB *pub_blob;

    CRYPT_PUBKEY_INFO_HEADER *tPublicKeyParam =
        (CRYPT_PUBKEY_INFO_HEADER*) & pub_blob->tPublicKeyParam;

    BLOBHEADER *BlobHeader =
        (BLOBHEADER*) & tPublicKeyParam->BlobHeader;

    BlobHeader->bType = PUBLICKEYBLOB;
    BlobHeader->bVersion = BLOB_VERSION; // 0x20 current
    BlobHeader->reserved = 0x00;
    BlobHeader->aiKeyAlg = CALG_GR3410EL;

    CRYPT_PUBKEYPARAM *KeyParam =
        (CRYPT_PUBKEYPARAM*) &tPublicKeyParam->KeyParam;

    KeyParam->Magic = GR3410_1_MAGIC;
    KeyParam->BitLen = GOST3410_PUBKEY_SIZE * 8; 

    memcpy(pub_blob->bASN1GostR3410_94_PublicKeyParameters, // Name is 94, but param can be 2001 also. :)
           default_params_3410_2001,
           sizeof(default_params_3410_2001));


    // Fill CRYPT_PUBLICKEYBLOB->bPublicKey...
    void *key_data = ((void *)pub_blob) + RAW_PUB_OFFSET;
    memcpy(key_data, GostR3410-KeyTransport::ephemeralPublicKey, длинна_присланого);

	HCRYPTKEY hResPubKey = 0;
	CryptImportKey(hProvider, (BYTE*)pub_blob, PUBLICBLOBLEN, 0, 0, &hResPubKey)


4. Согласуем ключ обмена: импортируем полученный блоб, указав в качестве ключа обмена свой закрытый.


Код:
HCRYPTKEY our_priv = 0;
CryptGetUserKey(hProv, AT_KEYEXCHANGE, &our_priv);

HCRYPTKEY agr_key = 0;
CryptImportKey(hProv, pub_blob, PUBLICBLOBLEN, our_priv, 0, &agr_key);

//CALG_SIMPLE_EXPORT нужно только если премастер вы будете использовать "как положено".
//ALG_ID ke_alg = CALG_SIMPLE_EXPORT; 
// А если хотите в открытом виде - ставьте CALG_PRO_EXPORT.
ALG_ID ke_alg = CALG_PRO_EXPORT;
CryptSetKeyParam(agr_key, KP_ALGID, (LPBYTE)&ke_alg, 0);



5. Собираем CRYPT_SIMPLEBLOB для премастера.

Код:
// Опять таки, зависит от используемых параметров.
static const BYTE default_params_28147[] = { 0x30, 0x09, 0x06, 0x07,
                                             0x2A, 0x85, 0x03, 0x02,
                                             0x02, 0x1F, 0x01 };

// We decrement it by 4 due to 4 bytes alignment of BYTE bEncryptionParamSet[1] array.
/// @bug incompatible with x64?
const size_t REAL_CRYPT_SIMPLEBLOB_LEN = sizeof(CRYPT_SIMPLEBLOB)
                                       + sizeof(default_params_28147) - 4;

CRYPT_SIMPLEBLOB *blob = ...

    blob->tSimpleBlobHeader.BlobHeader.bType = SIMPLEBLOB;
    blob->tSimpleBlobHeader.BlobHeader.bVersion = BLOB_VERSION; // 0x20 current.
    blob->tSimpleBlobHeader.BlobHeader.reserved = 0x0;
    //CALG_TLS1_MASTER  нужно только если премастер вы будете использовать "как положено".
    // // А если хотите в открытом виде - ставьте CALG_G28147.
    blob->tSimpleBlobHeader.BlobHeader.aiKeyAlg = CALG_G28147; // !CALG_TLS1_MASTER - иначе в открытом виде не получиться!!!

    blob->tSimpleBlobHeader.Magic = G28147_MAGIC;
    blob->tSimpleBlobHeader.EncryptKeyAlgId = CALG_G28147;
	
	memcpy(keyBlob->bEncryptionParamSet, default_params_28147, sizeof(default_params_28147));


	memcpy(keyBlob->bSV, 			GostR3410-KeyTransport::transportParameters::ukm, 			SEANCE_VECTOR_LEN);
	memcpy(keyBlob->bEncryptedKey, 	GostR3410-KeyTransport::sessionEncryptedKey::encryptedKey, 	G28147_KEYLEN);
	memcpy(keyBlob->bMacKey, 		GostR3410-KeyTransport::sessionEncryptedKey::macKey, 		EXPORT_IMIT_SIZE);



6. Получаем премастер.
Код:

DWORD dataLen = REAL_CRYPT_SIMPLEBLOB_LEN;
HCRYPTKEY premaster_key;

CryptImportKey(hProv,
                      (BYTE*)blob,
                      REAL_CRYPT_SIMPLEBLOB_LEN,
                      agr_key,
                      CRYPT_EXPORTABLE,
                      &premaster_key);



7. В реальном коде предусматриваем обработку ошибок.

8. Если есть потребность получить прематер в чистом виде - экспортируем его снова на каком-нибудь сгенерированном ключе и извлекаем из блоба.



Отредактировано пользователем 13 марта 2011 г. 23:22:07(UTC)  | Причина: Не указана

Offline SergeyFedotov  
#10 Оставлено : 30 мая 2011 г. 16:50:33(UTC)
SergeyFedotov

Статус: Новичок

Группы: Участники
Зарегистрирован: 30.05.2011(UTC)
Сообщений: 6
Откуда: Россия

Не очень понятен следующий момент: для генерации ключа согласования (KEK) необходим IV (UKM).
Вызов CryptImportKey(hProv, pub_blob, PUBLICBLOBLEN, our_priv, 0, &agr_key), с помощью которого выполняется эта операция не позволяет задать IV.
Вопрос: откуда берётся UKM при получении ключа согласования?
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
2 Страницы12>
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.