14.09.2004 16:38:59Экспорт секретного ключа ключевой пары Ответов: 1
Иван Куликов
Все попытки эспортировать секретный ключ в блоб типа PRIVATEKEYBLOB безуспешны. Прочитал все, что по этому вопросу имеется на форуме. Не помогает. Ваш тестовый пример с параметрами вызова -makecet CN=MyCert -ex NewCert.cer pubkey.key qwertyuiop не работает. Привожу фрагмент вашего теста:
if (bExport)
{
DWORD dwWritten;

/* Create Certificate file*/
hCertFile = CreateFile(szCertFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hCertFile == INVALID_HANDLE_VALUE)
{
printf("CreateFile failed with %d\n", GetLastError());
__leave;
}

/* Write encoded Certificate to file*/
bResult = WriteFile(hCertFile, (LPVOID)bpEncodedCert, dwSize, &dwWritten, NULL);
if (!bResult)
{
printf("WriteFile failed with %d\n", GetLastError());
__leave;
}

/* Destroy previous hash*/
if (hHash) CryptDestroyHash(hHash);
hHash = 0;

/* Create hash*/
//bResult = CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash);
bResult = CryptCreateHash(hProv, CALG_GR3411 , 0, 0, &hHash);
if (!bResult)
{
printf("CryptCreateHash failed with %x\n", GetLastError());
__leave;
}

/* Hash password*/
bResult = CryptHashData(hHash, (LPBYTE)szPassword, strlen(szPassword), 0);
if (!bResult)
{
printf("CryptHashData failed with %x\n", GetLastError());
__leave;
}

/* Derive Session Key from hash*/
//bResult = CryptDeriveKey(hProv, CALG_RC4, hHash, CRYPT_EXPORTABLE, &hSessionKey);
bResult = CryptDeriveKey(hProv, CALG_G28147, hHash, CRYPT_EXPORTABLE, &hSessionKey);
if (!bResult)
{
printf("CryptDeriveKey failed with %x\n", GetLastError());
__leave;
}

/* Get size of exported key blob*/
bResult = CryptExportKey(hPubKey, hSessionKey, PRIVATEKEYBLOB, 0, NULL, &dwSize);
if (!bResult)
{
printf("CryptExportKey failed with %x\n", GetLastError());
__leave;
}

/* Allocate memory for exported key blob*/
pbExportedKey = (LPBYTE)HeapAlloc(hHeap, 0, dwSize);
if (!pbExportedKey)
{
printf("Unable to allocate memory for exported key\n");
__leave;
}

/* Get exported key blob*/
bResult = CryptExportKey(hPubKey, hSessionKey, PRIVATEKEYBLOB,
0, pbExportedKey, &dwSize);
if (!bResult)
{
printf("CryptExportKey failed with %x\n", GetLastError());
__leave;
}
Уже при попытке определения размера блоба CryptExportKey(hPubKey, hSessionKey, PRIVATEKEYBLOB, 0, NULL, &dwSize) возвращает FALSE даже после того, как все остальные функции отработали с результатом TRUE (после того, как импортные идентификаторы алгоритмов я заменил на ваши). Не могли бы вы разместить на форуме заведомо работающий минимальный пример эспорта серетного ключа в PIVATEKEYBLOB? Или подправить этот пример. Может быть, нужно установить какие-то параметры ключа экспорта или импортируемого ключа? Я это пробовал: вектор инициализации и т.д. Не помогает. Обычная генерация сессионного ключа (с использованием CryptGenKey, а не CryptDeriveKey) тоже не помогает. Судя по переписке это актуальный вопрос.
 
Ответы:
14.09.2004 17:28:55Василий
Пример в csptest-е, конечно, неуниверсальный. Здесь критика справедлива. А с нашим CSP работать не будет, даже после замены алгоритмов на ГОСТовые. Дело в том, что экспорт закрытого ключа пары делается не на сессионном ключе, а на ключе обмена. Его можно сделать либо по алгоритму Диффи-Хеллмана, либо лёгким движением руки из сессионного:
DWORD algid_export = CALG_PRO_EXPORT;
CryptSetKeyParam( hSessionKey, KP_ALGID, (BYTE*)&algid_export, 0 );

И тогда экспорт будет успешным