15.11.2006 11:06:19Дайте примерчик? =( Ответов: 40
DarkF0x
Доброе утро! ЧТо за вилы с этим Crypto API? Никак не могу получить открытый ключ из контейнера, чего только не делал!
Исходник :
DWORD namesize;
DWORD s;
char provName[255];
int i = 0;


while (CryptEnumProviders(i, 0, 0, &s, 0, &namesize))
{
if (CryptEnumProviders(i, 0, 0, &s, provName, &namesize))
{

HCRYPTPROV hProv;

if (!CryptAcquireContext(&hProv, NULL, provName, s, CRYPT_VERIFYCONTEXT))
return 0;


DWORD size;
BYTE result[255];
DWORD fParam = CRYPT_FIRST;

std::cout << provName << std::endl;


while ( CryptGetProvParam(hProv, PP_ENUMCONTAINERS, NULL, &size, fParam) )
{

memset(&result,0,255);

CryptGetProvParam(hProv, PP_ENUMCONTAINERS, result, &size, fParam);

fParam = 0;

std::cout << result << std::endl;

HCRYPTPROV tmpProv = NULL;
HCRYPTKEY hPublicKey = NULL;


if (CryptAcquireContext(&tmpProv, (LPCSTR)result, provName, s, CRYPT_VERIFYCONTEXT))
{

if (CryptGetUserKey(htmpProv, AT_SIGNATURE | AT_KEYEXCHANGE, &hPublicKey))
std::cout << "&#206;&#234;&#242;&#240;&#251;&#242;&#251;&#233; &#234;&#235;&#254;&#247; &#239;&#238;&#235;&#243;&#247;&#229;&#237;" << std::endl;
else
ErrMsg();


CryptReleaseContext(tmpProv, 0);

} else
ErrMsg();


}


std::cout << "--------------------------------------------------------" << std::endl;

CryptReleaseContext(hProv, 0);
}


i++;
}


1. Получаею Имя и Тип криптопровайдера (ВСЕ ОК)
2. Получаю контекст криптопровайдера (ВСЕ ОК)
3. Получаю имя контейнера (Тоже ВСЕ ОК)
4. Получаю контекст tmp криптопровайдера (используя полученные тип, имя контейнера и имя криптопровайдера)
и Вот тут Все время ошибка : Указаны неправильные флаги.

Пробовал без повторного получения контекста криптопровайдера в tmp, получать октрытый ключ сразу после определения имени контейнера, нифига не выходит, орет уже на функцию CryptGetUserKey, что типа Ключи не найдены! Ну что за лажа? ДУмал, что ключей правда нет в контейнере, попробовал сгенерировать пару, ругается что ключи в контейнере уже есть, а ключи действительно есть, при просмотре сертификата средствами CryptoPRO CSP, открытый ключик лежит в виде hex строчки... Вот как его выцерапать из контейнера? Ведь открытый то ключ должен без проблем получаться?
 
Ответы:
15.11.2006 13:31:25Kirill Sobolev
CRYPT_VERIFYCONTEXT лишний.
When this flag is set, the application has no access to the persisted private keys of public/private key pairs, and the pszContainer parameter must be set to NULL.
15.11.2006 15:41:25DarkF0x
Если не трудно подскажите какой флаг указывать при получении контекста?
15.11.2006 15:47:19DarkF0x
Хм.. Странно... Выставил флаг в 0, ругается что мол вставьте ключевой носитель для пользователя такого-то...
Ключи не найдены!
15.11.2006 16:03:25Kirill Sobolev
0 и надо. Видимо контейнер находится на съемном носителе, поэтому CSP и просит его вставить.
15.11.2006 16:25:16DarkF0x
Да нет в реестре. Смотрю руками: Control Panel->CryptoPRO CSP->Сервис->Просмотреть сертификаты в контейнере->Выбираю контейнер (считыватель реестр)->Сертификат для просмотра->Свойства->Состав->и там в списке есть такая строчка Открытый ключ ГОСТ Р 34.10-94 (1024 bits)
А также Использование ключа : Цифровая подпись, неотрекаемость и т.п. Отпечаток - hex строка..
То есть к чему я, ключик по всей видимости есть в контейнере, но вот достучаться до него не могу, также смотрел в реестре, там тоже есть
HKEY_LOCAL_MACHINE\SOFTWARE\Crypto Pro\Settings\USERS\S-1-5-21-1177238915-1606980848-1060284298-6016\Keys\
Имя контейнера\ в нем 6 ключиков лежит...
программно нифига не получается, постоянно требует вставить ключевой носитель Реестр
15.11.2006 16:27:28DarkF0x
Правда у меня демострационный CryptoPro CSP (30 дней) может из-за этого?
15.11.2006 16:42:54Kirill Sobolev
И 30 дней прошло уже?
15.11.2006 16:44:16DarkF0x
Неа... Еще 21 день остался..
15.11.2006 17:15:20Kirill Sobolev
А "Имя контейнера" Вы в CryptAcquireContext указываете? Возможно, что для пользователя нет контейнера по умолчанию.
15.11.2006 17:19:35DarkF0x
Указываю... Самое интересное тогда получает контекст, но когда вызываю CryptGetUserKey, ругается что ключи не найдены! =(
15.11.2006 17:45:56Kirill Sobolev
А там есть ключ обмена?
15.11.2006 17:48:31DarkF0x
Извиняюсь за ламерство (пока плохо разбераюсь в теме!), а что такое ключ обмена? Как такового в списке нет!
15.11.2006 18:16:56Kirill Sobolev
Ключ обмена - это ключ, который позволяет обмениваться шифрованными сообщениями.
Вы же вызываете CryptGetUserKey с AT_KEYEXCHANGE, это означает что пытаетесь достать именно ключ обмена.
15.11.2006 18:41:05DarkF0x
А для того, чтобы достать открытый ключик для проверки цифровой подписи, мне нужно юзать AT_SIGNATURE?
16.11.2006 2:40:12maxdm
В контейнере может быть любой из ключей AT_xxx, а может быть и оба. AT_SIGNATURE можно использовать только для подписи. AT_KEYEXCHANGE - и для шифрования и для подписи.
16.11.2006 2:41:17maxdm
А ключ для проверки подписи обычно берут из сертификата.
16.11.2006 9:12:10DarkF0x
Ага, вот уже теплее стало, хоть что-то... Главное теперь разобраться как до сертификата достучаться и ключик получить! =)
16.11.2006 11:55:48Kirill Sobolev
Сертификат должен быть доступен на машине, где подпись проверятся. Хранить его можно, например, в хранилище или в файле.
16.11.2006 12:00:03Darkf0x
Сертификат я получил =) Теперь разобраться бы чего дальше делать! =)
HCERTSTORE hStoreHandle;

if ( !( hStoreHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER,
//CERT_SYSTEM_STORE_LOCAL_MACHINE,
L"MY")))
{
printf("Can not open Store MY.\n");
return 0;
}

PCCERT_CONTEXT pSignerCert = NULL;

if(pSignerCert = CertFindCertificateInStore(hStoreHandle,PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
0, CERT_FIND_SUBJECT_STR, L"test", NULL))
{
printf("Certificates Found %s\n");




}
else
printf( "Certificates not Found.\n");

if(pSignerCert)
CertFreeCertificateContext(pSignerCert);

CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);
16.11.2006 12:11:40Kirill Sobolev
А какая глобальная задача стоит?
16.11.2006 12:25:53DarkF0x
на самом деле все просто! Мне нужно проверить ЭЦП у полученного документа и все! Документ в формате XML, в одном из тегов сообщения лежит ЭЦП, мне нужно проверить, что документ не изменился в процессе передачи! То есть проверить ЭЦП полученного сообщения!
16.11.2006 12:59:21Kirill Sobolev
CryptoAPI не работает с XML, может быть проще воспользоваться тем API которым этот XML подписывался?
16.11.2006 13:20:57DarkF0x
Да не.. Вы меня не поняли! =) XML я парсю сам, программно! Я знаю в каком теге лежит ЭЦП.
Суть вот в чем :
1. Взять ЭЦП1 из XML сообщения (Я беру её без проблем)
2. Создать своё ЭЦП2 (Хеш нужных полей + Открытый ключ из сертификата)
3. Сравнить ЭЦП1 и ЭЦП2
Вот и все! Сертификат я получил, теперь не совсем понятно как из него выцерапать открытый ключ, ну и создать Хэш значение..
16.11.2006 13:29:51Kirill Sobolev
А ЭЦП1 как получается?
16.11.2006 13:48:41Василий
> 1. Взять ЭЦП1 из XML сообщения (Я беру её без проблем)
> 2. Создать своё ЭЦП2 (Хеш нужных полей + Открытый ключ из сертификата)
> 3. Сравнить ЭЦП1 и ЭЦП2

При создании ЭЦП одних и тех же данных каждый раз будет разный результат, т.к. в процессе участвует случайное число.
16.11.2006 13:55:19DarkF0x
Блин! Гемморой... Как тогда быть? Как аутентифициаровать документ? Проверить, что он не был изменен?
16.11.2006 14:00:07Василий
При проверке подписи не нужен закрытый ключ.
Если при подписывании используется сертификат, то для проверки можно использовать открытый ключ из сертификата.
Если не используется - можно просто добавить в документ поле, в которое засунуть экспортированный в блоб открытый ключ подписавшего.
16.11.2006 14:10:48DarkF0x
ТАк мне закрытый ключ и не нужен, яж писал выше, открытый ключик мне получить надо! Кста, а вот ЭЦП в каждом случае (для каждого документа) будет разное, потому что при формировании ЭЦП используется хэш значение определенных полей и открый ключ! Блин запутался совсем! Тогда как мне понять был изменен документ или нет?
16.11.2006 16:41:35Василий
При создании подписи каждый раз будет получаться разное значение ЭЦП.
При проверке подписи используются:
- хеш документа
- открытый ключ подписавшего
- значение ЭЦП (оно не вычисляется, а берётся готовое)
Если документ изменится, то изменится его хеш и подпись станет неверной.
16.11.2006 17:36:51DarkF0x
Вроде прочухал... =) Теперь нужно грамотно реализовать сие!
Есть пробелма еще в том что у меня стоит VC++ 6
А в хидере wincrypt.h нет прототипа функции CryptAcquireCertificatePrivateKey (для получения криптопровайдера связано с нужным сертификатом), криптопровайдер нужно тогда получать получать другой функцией, отсюда вопрос : Как оперделить что это именно тот криптопровайдер и сертификат соответствует ему!
Кстати, а хэш вычисляется всегда по одному алгоритму или в КриптоПро свой алгоритм формирования хэша?
16.11.2006 17:39:17DarkF0x
Почитал в MSDN что вроде как хэш создается с использованием
CALG_MD5... КриптоПро тоже использует этот метод создания хэша, или у него другой (свой)?
17.11.2006 10:45:13Kirill Sobolev
Есть предложение формировать подпись в формате PKCS7 и переложить всю увлекательную работу по инициализации провайдера на CryptoAPI
17.11.2006 10:48:24Василий
Алгоритм хеша:
ГОСТ P 34.11-94

А вот CryptAcquireCertificatePrivateKey стопудово не нужна при проверке подписи.

Вообще, вопрос - вычисление ЭЦП (на стороне отправителя) тоже будет делать Ваша программа?
Если да, посмотрите наш пример SigningHash из http://www.cryptopro.ru/cryptopro/download/60763684-1BBD-4A65-B475-A2D86A7CDD24/30/3293/sdk.zip
17.11.2006 12:41:54DarkF0x
Нет, на стороне клиента работает не мой код, но у них стоит
наш сертификат ну а софт CryptoPro 2.0 (криптография ГОСТЫ реализованные в CryptoPro 2.0) У меня криптографические библиотеко аналогичные стоят стоит, и сертификат тоже такой же как у клиента, они подписывают, мне только верифицировать нужно и все...
17.11.2006 13:57:56Darkf0x
Вроде написал, сначала создаю подпись, потом её верифицирую, тока своль ругается, что мол Неправильная подпись.. Пока не вчухал почему... Вот исходничек если интересно:
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0400
#endif

#include <windows.h>
#include <stdio.h>
#include <iostream>
#include <wincrypt.h>


#pragma comment (lib, "Crypt32.lib")
#pragma comment (lib, "Advapi32.lib")
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
BYTE *ecp;
DWORD ecplen;
//-------------------------------------------------------------------------------------
BYTE* pbMessage = (BYTE*)"Hello world";
DWORD cbMessage = (DWORD)strlen((char*) pbMessage)+1;
//-------------------------------------------------------------------------------------
DWORD AlgID;
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
void ErrMsg()
{
char err_message[1000];
DWORD err = GetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) err_message, sizeof(err_message), NULL );

sprintf(err_message,"%s - %d",err_message,err);

CharToOem(err_message,err_message);
std::cout << err_message << std::endl;
std::cout << "-----------------------" << std::endl;
}
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
void print_signature(DWORD cbSigned, BYTE* pbSigned)
{
for(DWORD i=0; i < cbSigned; i++)
{
printf("%2.2x", pbSigned[i]);
if ((i+1)%32 == 0) printf("\n");
}
}
//-------------------------------------------------------------------------------------
// &#209;&#238;&#231;&#228;&#224;&#229;&#236; &#239;&#238;&#239;&#232;&#241;&#252;
//-------------------------------------------------------------------------------------
bool CreateECP()
{

// &#206;&#242;&#234;&#240;&#251;&#226;&#224;&#229;&#236; &#245;&#240;&#224;&#237;&#232;&#235;&#232;&#249;&#229; &#241;&#229;&#240;&#242;&#232;&#244;&#232;&#234;&#224;&#242;&#238;&#226;

HCERTSTORE hStoreHandle;

if (!( hStoreHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL,CERT_SYSTEM_STORE_CURRENT_USER, L"MY")))
{
ErrMsg();
return 0;
}

// &#207;&#238;&#235;&#243;&#247;&#224;&#229;&#236; &#243;&#234;&#224;&#231;&#224;&#242;&#229;&#235;&#252; &#237;&#224; &#237;&#224;&#248; &#241;&#229;&#240;&#242;&#232;&#244;&#232;&#234;&#224;&#242;

PCCERT_CONTEXT pSignerCert;

if (pSignerCert = CertFindCertificateInStore(hStoreHandle,PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,0, CERT_FIND_SUBJECT_STR,
L"test2",NULL))
printf("Certificate found...\n");
else
ErrMsg();



// &#207;&#229;&#240;&#229;&#236;&#229;&#237;&#237;&#251;&#229; &#228;&#235;&#255; &#243;&#234;&#224;&#231;&#224;&#242;&#229;&#235;&#255; &#232; &#228;&#235;&#232;&#237;&#251; &#239;&#238;&#228;&#239;&#232;&#241;&#232;
BYTE *pbSignedMessageBlob;
DWORD cbSignedMessageBlob;


// &#209;&#238;&#231;&#228;&#224;&#229;&#236; &#232; &#231;&#224;&#239;&#238;&#235;&#237;&#255;&#229;&#236; &#241;&#242;&#240;&#243;&#234;&#242;&#243;&#240;&#243; &#228;&#235;&#255; &#241;&#238;&#231;&#228;&#224;&#237;&#232;&#255; &#246;&#232;&#244;&#240;&#238;&#238;&#226;&#238;&#233; &#239;&#238;&#228;&#239;&#232;&#241;&#232;
CRYPT_SIGN_MESSAGE_PARA SigParams;

SigParams.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);
SigParams.dwMsgEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
SigParams.pSigningCert = pSignerCert;
SigParams.HashAlgorithm.pszObjId = pSignerCert->pCertInfo->SignatureAlgorithm.pszObjId;
AlgID = CertOIDToAlgId(pSignerCert->pCertInfo->SignatureAlgorithm.pszObjId);
SigParams.HashAlgorithm.Parameters.cbData = NULL;
SigParams.cMsgCert = 0;
SigParams.rgpMsgCert = NULL;
SigParams.cAuthAttr = 0;
SigParams.dwInnerContentType = 0;
SigParams.cMsgCrl = 0;
SigParams.cUnauthAttr = 0;
SigParams.dwFlags = 0;
SigParams.pvHashAuxInfo = NULL;
SigParams.rgAuthAttr = NULL;


const BYTE* MessageArray[] = {pbMessage};
DWORD MessageSizeArray[1];
MessageSizeArray[0] = cbMessage;

// &#207;&#238;&#235;&#243;&#247;&#224;&#229;&#236; &#228;&#235;&#232;&#237;&#243; &#225;&#243;&#244;&#229;&#240;&#224; &#239;&#238;&#228;&#239;&#232;&#241;&#232;

if(CryptSignMessage(&SigParams, // &#243;&#234;&#224;&#231;&#224;&#242;&#229;&#235;&#252; &#237;&#224; SigParams
TRUE, // &#239;&#238;&#228;&#239;&#232;&#241;&#252; &#241;&#238;&#231;&#228;&#224;&#229;&#242;&#241;&#255; &#238;&#242;&#228;&#229;&#235;&#252;&#237;&#238;
1, // &#247;&#232;&#241;&#235;&#238; &#241;&#238;&#238;&#225;&#249;&#229;&#237;&#232;&#233;
MessageArray, // &#241;&#238;&#238;&#225;&#249;&#229;&#237;&#232;&#229;
MessageSizeArray, // &#228;&#235;&#232;&#237;&#224; &#241;&#238;&#238;&#225;&#249;&#229;&#237;&#232;&#255;
NULL, // &#225;&#243;&#244;&#229;&#240; &#228;&#235;&#255; &#239;&#238;&#228;&#239;&#232;&#241;&#232;
&cbSignedMessageBlob)) // &#240;&#224;&#231;&#236;&#229;&#240; &#225;&#243;&#244;&#229;&#240;&#224;

printf("ECP Size %d.\n",cbSignedMessageBlob);

else
ErrMsg();


// &#226;&#251;&#228;&#229;&#235;&#255;&#229;&#236; &#239;&#224;&#236;&#255;&#242;&#252; &#239;&#238;&#228; &#239;&#238;&#228;&#239;&#232;&#241;&#252;
if(!(pbSignedMessageBlob = new BYTE[cbSignedMessageBlob])) ErrMsg();


// &#244;&#238;&#240;&#236;&#232;&#240;&#243;&#229;&#236; &#239;&#238;&#228;&#239;&#232;&#241;&#252;
if(CryptSignMessage(&SigParams, // &#243;&#234;&#224;&#231;&#224;&#242;&#229;&#235;&#252; &#237;&#224; SigParams
TRUE, // &#239;&#238;&#228;&#239;&#232;&#241;&#252; &#241;&#238;&#231;&#228;&#224;&#229;&#242;&#241;&#255; &#238;&#242;&#228;&#229;&#235;&#252;&#237;&#238;
1, // &#247;&#232;&#241;&#235;&#238; &#241;&#238;&#238;&#225;&#249;&#229;&#237;&#232;&#233;
MessageArray, // &#241;&#238;&#238;&#225;&#249;&#229;&#237;&#232;&#229;
MessageSizeArray, // &#228;&#235;&#232;&#237;&#224; &#241;&#238;&#238;&#225;&#249;&#229;&#237;&#232;&#255;
pbSignedMessageBlob, // &#225;&#243;&#244;&#229;&#240; &#228;&#235;&#255; &#239;&#238;&#228;&#239;&#232;&#241;&#232;
&cbSignedMessageBlob)) // &#240;&#224;&#231;&#236;&#229;&#240; &#225;&#243;&#244;&#229;&#240;&#224;
{
printf("ECP:\n");
print_signature(cbSignedMessageBlob, pbSignedMessageBlob);
ecp = new BYTE[cbSignedMessageBlob];
memset(ecp,0,cbSignedMessageBlob);
memcpy(ecp,pbSignedMessageBlob,cbSignedMessageBlob);
ecplen = cbSignedMessageBlob;
}
else
ErrMsg();

if (pbSignedMessageBlob) delete pbSignedMessageBlob;

if(pSignerCert) CertFreeCertificateContext(pSignerCert);

if(!CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG)) ErrMsg();

return 0;
}
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
// &#207;&#240;&#238;&#226;&#229;&#240;&#255;&#229;&#236; &#239;&#238;&#228;&#239;&#232;&#241;&#252;
//-------------------------------------------------------------------------------------
bool VerifyECP()
{

bool fl = false;



HCERTSTORE hStoreHandle;

if ( !( hStoreHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"MY")))
{
ErrMsg();
return 0;
}

// &#207;&#238;&#235;&#243;&#247;&#224;&#229;&#236; &#243;&#234;&#224;&#231;&#224;&#242;&#229;&#235;&#252; &#237;&#224; &#237;&#224;&#248; &#241;&#229;&#240;&#242;&#232;&#244;&#232;&#234;&#224;&#242;

PCCERT_CONTEXT pSignerCert = NULL;

if(pSignerCert = CertFindCertificateInStore(hStoreHandle,PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
0, CERT_FIND_SUBJECT_STR, L"test2", NULL))
printf("Certificates Found\n");
else
ErrMsg();


if(pSignerCert)
{
HCRYPTKEY hKey = NULL;

CERT_PUBLIC_KEY_INFO keyInfo = pSignerCert->pCertInfo->SubjectPublicKeyInfo;


DWORD namesize;
DWORD s;
char provName[255];
int i = 0;


HCRYPTPROV hProv = NULL;

while (CryptEnumProviders(i, 0, 0, &s, 0, &namesize))
if (CryptEnumProviders(i, 0, 0, &s, provName, &namesize))
if (CryptAcquireContext(&hProv, "bspb_test", provName, s, 0))
break;
else
i++;

if (CryptImportPublicKeyInfo(hProv,PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, &keyInfo, &hKey))
{

// &#209;&#238;&#231;&#228;&#224;&#229;&#236; &#239;&#243;&#241;&#242;&#238;&#233; hash &#238;&#225;&#250;&#229;&#234;&#242;
HCRYPTHASH hHash;


if(CryptCreateHash(hProv, AlgID, 0, 0, &hHash))
printf("Hash Object Created.\n");
else
ErrMsg();

//--------------------------------------------------------------------
// &#194;&#251;&#247;&#232;&#241;&#235;&#255;&#229;&#236; hash &#228;&#235;&#255; &#237;&#224;&#248;&#229;&#227;&#238; &#241;&#238;&#238;&#225;&#249;&#229;&#237;&#232;&#255;
if(CryptHashData(hHash, pbMessage,cbMessage, 0))
printf("Hash Object Calculate: \n");
else
ErrMsg();

// &#194;&#229;&#240;&#232;&#244;&#232;&#246;&#232;&#240;&#243;&#229;&#236; &#241;&#238;&#238;&#225;&#249;&#229;&#237;&#232;&#229;
if(CryptVerifySignature(hHash, // &#228;&#229;&#241;&#234;&#240;&#232;&#239;&#242;&#238;&#240; &#237;&#224; hash &#238;&#225;&#250;&#229;&#234;&#242;
ecp, // &#243;&#234;&#224;&#231;&#224;&#242;&#229;&#235;&#252; &#237;&#224; &#239;&#238;&#228;&#239;&#232;&#241;&#252;
ecplen, // &#228;&#235;&#232;&#237;&#224; &#239;&#238;&#228;&#239;&#232;&#241;&#232;
hKey, // &#228;&#229;&#241;&#234;&#240;&#232;&#239;&#242;&#238;&#240; &#237;&#224; public key
NULL,0))
{
printf("ECP Right...\n");
fl = true;
} else
ErrMsg();

// &#206;&#241;&#226;&#238;&#225;&#238;&#230;&#228;&#224;&#229;&#236; &#239;&#224;&#236;&#255;&#242;&#252;
// &#211;&#237;&#232;&#247;&#242;&#238;&#230;&#224;&#229;&#236; &#228;&#229;&#241;&#234;&#240;&#232;&#239;&#242;&#238;&#240;&#251;
if(hHash) CryptDestroyHash(hHash);
if(hKey) CryptDestroyKey(hKey);
if(hProv) CryptReleaseContext(hProv, 0);


}
CertFreeCertificateContext(pSignerCert);
}

CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG);

return fl;

}
//-------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------
int main(int carg,LPSTR* args)
{

ecp = NULL;

CreateECP();

printf("\n\n\n");

VerifyECP();

if (ecp) delete ecp;

return 0;
}
17.11.2006 14:29:12Василий
Странная идея - подписывать высокоуровневой функцией (CryptSignMessage), а проверять низкоуровневыми.
Вы уж определитесь...
17.11.2006 15:33:12DarkF0x
А в чем проблема то? Почему нельзя проверять низкоуровневой?
17.11.2006 15:49:42darkf0x
Дайте пример подписи и проверки подписи который будет работать на VC++ 6
17.11.2006 18:11:34Василий
> Почему нельзя проверять низкоуровневой?
Потому что высокоуровневая функция подписывает не сам открытый текст, а преобразовывает его. Если вы знаете, как она это делает - тогда вперёд. Только вот - зачем?
Тем более, что, по вашим словам, вам нужно только проверять подпись...

Готового примера для VC6 нет - очень уж старинная среда.
Возьмите исходник по ссылке, что я прислал - он практически годится, с небольшими изменениями в части работы с сертификатами.

Схема:
создание подписи:
- по сертификату получить хендл контейнера ключа (это есть у вас)
- посчитать хеш (это есть у вас в ф-и проверки)
- вычислить ЭЦП ф-ей CryptSignHash

проверка подписи:
- из сертификата получить хендл открытого ключа (это есть у вас)
- посчитать хеш (это есть у вас)
- проверить ЭЦП ф-ей CryptVerifySignature (это есть у вас)
20.11.2006 14:51:06darkf0x
Ура! Заработало....