03.08.2007 12:10:48Как проверить соответствие сертификата закрытым ключам Ответов: 7
Евгений
Вообщем-то вопрос в теме. Возможно произвести проверку? Если да, то каким способом.
 
Ответы:
03.08.2007 12:16:55Василий
Конечно, можно.
Собственно, например, при установке сертификата кнопкой "Установить личный сертификат" (панель КриптоПро CSP - Сервис) это делается.

Вопрос - нужна программная проверка или ручная (когда пользователь хочет увидеть значение открытого ключа из контейнера и сравнить его с ключом из сертификата)?
03.08.2007 12:18:13maxdm
Есть несколько способов.
Например такой:
HRESULT
WINAPI
MatchPublicPrivateKeys(
PCCERT_CONTEXT pCertContext,
DWORD dwFlags,
LPWSTR pwszPin)
{
PCRYPT_KEY_PROV_INFO pCryptKeyProvInfo = NULL;
HCRYPTPROV hProv = 0;
DWORD cbData = 0;
PCERT_PUBLIC_KEY_INFO pInfo = NULL;
CHAR szPin[MAX_PATH];
HRESULT res = S_OK;
DWORD provType = 0;

dwFlags;


if(!CertGetCertificateContextProperty(
pCertContext,
CERT_KEY_PROV_INFO_PROP_ID,
NULL,
&cbData))
{
res = GetLastError();
DbPrintf ((MODNAME L"!CERT_KEY_PROV_INFO_PROP_ID property\n"));
goto ReleaseResource;
}
pCryptKeyProvInfo = (PCRYPT_KEY_PROV_INFO)malloc(cbData);
if (!pCryptKeyProvInfo)
{
res = ERROR_NOT_ENOUGH_MEMORY;
goto ReleaseResource;
}
if(!CertGetCertificateContextProperty(
pCertContext,
CERT_KEY_PROV_INFO_PROP_ID,
pCryptKeyProvInfo,
&cbData))
{
res = GetLastError();
DbPrintf ((MODNAME L"!CERT_KEY_PROV_INFO_PROP_ID property\n"));
goto ReleaseResource;
}
if (!CryptAcquireContextW (
&hProv,
pCryptKeyProvInfo->pwszContainerName,
pCryptKeyProvInfo->pwszProvName,
pCryptKeyProvInfo->dwProvType,
pCryptKeyProvInfo->dwFlags&~CERT_SET_KEY_CONTEXT_PROP_ID))
{

res = GetLastError();
DbPrintf ((MODNAME L"!CryptAcquireContextW Failed\n"));
goto ReleaseResource;
}
if (!WideCharToMultiByte(
CP_ACP,
0,
pwszPin,
(int)wcslen (pwszPin) + 1,
szPin,
MAX_PATH,
NULL,
NULL))
{
res = GetLastError();
DbPrintf ((MODNAME L"!WideCharToMultiByte Failed\n"));
goto ReleaseResource;
}
if (!CryptSetProvParam(
hProv,
PP_KEYEXCHANGE_PIN,
(PBYTE)szPin,
0))
{
res = GetLastError();
DbPrintf ((MODNAME L"!CryptSetProvParam Failed\n"));
goto ReleaseResource;
}
cbData = sizeof (DWORD);
if (!CryptGetProvParam(
hProv,
PP_PROVTYPE,
(PBYTE)&provType,
&cbData,
0))
{
res = GetLastError();
DbPrintf ((MODNAME L"!CryptGetProvParam PP_PROVTYPE Failed\n"));
goto ReleaseResource;
}
if (!CryptExportPublicKeyInfo(
hProv,
pCryptKeyProvInfo->dwKeySpec,
pCertContext->dwCertEncodingType,
NULL,
&cbData))
{
res = GetLastError();
DbPrintf ((MODNAME L"!CryptExportPublicKeyInfo Failed\n"));
goto ReleaseResource;
}
pInfo = (PCERT_PUBLIC_KEY_INFO)malloc(cbData);
if (!pInfo)
{
res = ERROR_NOT_ENOUGH_MEMORY;
goto ReleaseResource;
}
if (!CryptExportPublicKeyInfo(
hProv,
pCryptKeyProvInfo->dwKeySpec,
pCertContext->dwCertEncodingType,
pInfo,
&cbData))
{
res = GetLastError();
DbPrintf ((MODNAME L"!CryptExportPublicKeyInfo Failed\n"));
goto ReleaseResource;
}

if (!CertComparePublicKeyInfo (
pCertContext->dwCertEncodingType,
pInfo,
&pCertContext->pCertInfo->SubjectPublicKeyInfo))
{
res = 0x80090015;
DbPrintf ((MODNAME L"!key does not match certificate\n"));
goto ReleaseResource;
}
ReleaseResource:
if (hProv)
CryptReleaseContext(hProv, 0);
if (pInfo)
free (pInfo);
if (pCryptKeyProvInfo)
free (pCryptKeyProvInfo);

return res;
}
03.08.2007 12:18:58maxdm
или еще вариант - подписать что-нибудь на закрытом ключе, а проверить на ключе сертификата
03.08.2007 12:25:07Евгений
У меня есть сгенеренный ключ и сертификат *.cer. Нужно однозначно установить их принадлежность друг другу, желательно не через программный код. Просмотр сертификата в контейнере ничего не дает т.к. его там нет. (CryptoPRO CSP 2.0)
03.08.2007 12:31:29Василий
Можно воспользоваться утилитой csptest. Для CSP 3.0 эта утилита ставится автоматически в папку установки CSP (по умолчанию \Program Files\Crypto Pro\CSP на системном диске). Если у клиента CSP 2.0, то утилиту можно скачать по ссылке http://www.cryptopro.ru/cryptopro/products/csp/20/csptest-2-0.exe (и в дальнейшем использовать это имя файла)

Итак, проверка:
1. экспорт открытого ключа из контейнера в файл:

csptest -keyset -container имя -keytype exchange -export key.txt

2. Далее нужно открыть этот файл key.txt на просмотр (F3) в Far или Total Commander и выбрать вид представления – Hex (в Far это F4, в Total – меню Options - Hex)

3. Параллельно открыть файл сертификата – вкладка Состав, поле Открытый ключ.

Нужно сравнить последние 64 байта там и там.
03.08.2007 13:00:06Евгений
Ошибка :963:Error during CryptAcquireContext
Error number 80090017 (-2146893801)
Тип поставщика не определен.

Что сие значит. CryptoPRO на машине установлен.
03.08.2007 13:43:12Василий
Добавьте ещё опцию -provtype 75 в строку вызова