Статус: Сотрудник
Группы: Участники
Зарегистрирован: 17.10.2010(UTC) Сообщений: 147  Откуда: КРИПТО-ПРО Сказал «Спасибо»: 2 раз Поблагодарили: 10 раз в 9 постах
|
Для потомков: Получаем premaster_secret TLS средствами CryptoAPI на стороне СЕРВЕРА. Для случая если клиентский сертификат не используется. 1. Изучаем RFC 4490, особенно раздел 4.2.1 http://tools.ietf.org/html/rfc44902. Парсим структуру 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)
| Причина: Не указана
|