Статус: Участник
Группы: Участники
Зарегистрирован: 27.10.2017(UTC) Сообщений: 12
Сказал(а) «Спасибо»: 3 раз
|
Похоже, произошло недопонимание. Попробую переформулировать вопрос максимально четко и конкретно. Изначальный код функции, реализующий подпись: Код:
static HCRYPTPROV getSignContext(std::string name, std::string password)
{
std::lock_guard<std::mutex> lock(exclusiveMutex);
std::map<std::string, HCRYPTPROV>::iterator it = contextCache.find(name);
if (it != contextCache.end())
{
HCRYPTPROV result = it->second;
return result;
}
else
{
HCRYPTPROV hProv = 0;
if (!CryptAcquireContext(
&hProv,
name.c_str(),
NULL,
PROV_GOST_2001_DH,
0)){
printf("JNI: getSignContext break on CryptAcquireContext [%d] for [%s]\n", GetLastErrorLocal(), name.c_str());
return 0;
}
if (!CryptSetProvParam(hProv, PP_SIGNATURE_PIN, (BYTE*)password.c_str(), 0)){
printf("JNI: do_low_sign_hash break on CryptSetProvParam [%d]\n", GetLastErrorLocal());
// cleanUp(hHash, data);
return 0;
}
contextCache[name] = hProv;
return hProv;
}
}
BOOL do_low_sign_hash(BYTE * pbContent, DWORD cbContent, std::string certName, std::string password, BYTE_ARRAY * result)
{
HCRYPTHASH hHash = 0;
BYTE_ARRAY data = { pbContent, cbContent };
DWORD keySpec = AT_KEYEXCHANGE;
lanit::shared_lock_guard<lanit::shared_mutex> lock(rwMutex);
HCRYPTPROV hProv;
try {
hProv = getSignContext(certName, password);
if (!hProv){
printf("JNI: do_low_sign_hash break on acquiring signing context \n");
cleanUp(hHash, data);
return 0;
}
if (!CryptCreateHash(hProv, CALG_GR3411, 0, 0, &hHash)){
printf("JNI: do_low_sign_hash break on CryptCreateHash [%d]\n", GetLastErrorLocal());
cleanUp(hHash, data, hProv);
return 0;
}
if (!CryptSetHashParam(hHash, HP_OID, (BYTE*)OID_HashVerbaO, 0)){
printf("JNI: do_low_sign_hash break on CryptSetHashParam [%d]\n", GetLastErrorLocal());
cleanUp(hHash, data, hProv);
return 0;
}
if (!CryptHashData(hHash, pbContent, cbContent, 0)){
printf("JNI: do_low_sign_hash break on CryptHashData [%d]\n", GetLastErrorLocal());
cleanUp(hHash, data, hProv);
return 0;
}
result->size = 0;
if (!CryptSignHash(hHash, keySpec, NULL, 0, NULL, &(result->size))){
flipKeySpec(keySpec);
if (!CryptSignHash(hHash, keySpec, NULL, 0, NULL, &(result->size))){
printf("JNI: do_low_sign_hash break on CryptSignHash [%d]\n", GetLastErrorLocal());
cleanUp(hHash, data, hProv);
return 0;
}
}
result->blob = new BYTE[result->size];
BOOL isSuccessful = 1;
if (!CryptSignHash(hHash, keySpec, NULL, 0, result->blob, &result->size)){
isSuccessful = 0;
printf("JNI: do_low_sign_hash break on CryptSignHash final [%d]\n", GetLastErrorLocal());
}
CryptDestroyHash(hHash);
//CryptReleaseContext(hProv, 0);
return isSuccessful;
} catch (std::exception *e) {
printf((*e).what());
cleanUp(hHash, data, hProv);
return 0;
}
}
В нашем случае есть строгое ограничение использования именно сертифицированной версией CSP RC2 и нет возможности руководствоваться требованиями из несертифицированной CSP RC3. Ограничения на использование функцииии CryptSignHash() из документации RC2: "Разрешено использование только с ключевыми контейнерами, полученными ранее с помощью вызова CertGetCertificateContextProperty из сертификата, проверенного с помощью функции CertVerifyCertificateChainPolicy"Как мы понимаем, для выполнения требований из документации [RC2] необходимо: 1) получить ключевой контейнер при помощи функции CertGetCertificateContextProperty из сертификата 2) сертификат должен быть проверен с помощью функции CertVerifyCertificateChainPolicy (*) с выполнением первого пункта проблема, нет понимания, как его выполнить. Ниже реализация, которая на первый взгляд соответствует документации [RC2], однако она не работает, так как в функции [CertGetCertificateContextProperty] не поддерживается работа с параметром [CERT_KEY_PROV_HANDLE_PROP_ID] Код:
BOOL verifyCertificateChain(PCCERT_CONTEXT pCertContext)
{ ... в реализации этой ф-ии все понятно...}
static HCRYPTPROV getSignContext2(std::string name, std::string password)
{
std::lock_guard<std::mutex> lock(exclusiveMutex);
std::map<std::string, HCRYPTPROV>::iterator it = contextCache.find(name);
LPCSTR lpszCertSubject = (LPCSTR) name.c_str();
LPCSTR sPassword = (LPCSTR) password.c_str();
HCERTSTORE hStoreHandle = 0; // Äåñêðèïòîð õðàíèëèùà ñåðòèôèêàòîâ
PCCERT_CONTEXT pCertSender = NULL; // Êîíòåêñò ñåðòèôèêàòà îòïðàâèòåëÿ
HCRYPTPROV hProvSender = 0; // Äåñêðèïòîð CSP îòïðàâèòåëÿ
DWORD dwKeySpecSender;
// ---
char pszNameString[256];
PCCERT_CONTEXT pCertContext = NULL;
PCRYPT_KEY_PROV_INFO pData;
DWORD cbData;
DWORD dwPropId = 0;
void* pvData;
CRYPT_KEY_PROV_INFO *pCryptKeyProvInfo;
DWORD cbName;
DWORD dwKeySpec;
HCRYPTPROV hCryptProv; // CSP handle
CHAR pszName[1000];
pszName[0] = 0;
const char * stores[] = { "My" , "uMy" , "mMy", "Root" , "uRoot" , "mRoot" , "CA" , "mCA" , "uCA" , "AddressBook" , "uAddressBook" , "mAddressBook" , "SPC" , "uSPC" , "mSPC" };
DWORD cStores = 15;
printf("JNI: start function getSignContext2 name: %s password: %s\n", lpszCertSubject, sPassword);
if (it != contextCache.end())
{
HCRYPTPROV result = it->second;
printf("JNI: Get store handle. from [contextCache]\n");
return result;
}
else
{
//--------------------------------------------------------------------
for (DWORD i = 0; i < cStores; i++) {
printf("JNI: try find any certificate in [%s], use [CertOpenSystemStore] \n", stores[i]);
hStoreHandle = CertOpenSystemStore(0, stores[i]);
if(!hStoreHandle)
{
printf("JNI: Error getting store handle. [%d]\n", GetLastErrorLocal());
continue;
} else {
printf("JNI: getting store handle from: [%s]\n", stores[i]);
}
// Find the certificates in the system store.
while(pCertContext = CertEnumCertificatesInStore(hStoreHandle, pCertContext))
{
// find criptoProvider
if(!( CryptAcquireCertificatePrivateKey(
pCertContext,
0,
NULL,
&hCryptProv,
&dwKeySpec,
NULL)))
{
printf("CryptAcquireCertificatePrivateKey.\n");
}
cbName = 1000;
// Read the name of the key container.
if(CryptGetProvParam(
hCryptProv,
PP_CONTAINER,
(BYTE*)pszName,
&cbName,
0))
{
printf("CryptGetProvParam succeeded.\n");
printf("Key Container name: %s\n", pszName);
// string compare
if ( !strcmp( lpszCertSubject , pszName ) ) {
// printf("find is Successful ! \n");
break;
}
} else {
printf("Error reading key container name.\n");
}
} // end [ while(pCertContext = ... ]
// string compare
if ( !strcmp( lpszCertSubject , pszName ) ) {
printf("find is Successful ! \n");
break;
}
} // end [ for (DWORD ... ]
//--------------------------------------------------------------------
if (!verifyCertificateChain(pCertContext)){
throw "error verifyCertificateChain";
}
//--------------------------------------------------------------------
if(!CertGetCertificateContextProperty(
pCertContext,
CERT_KEY_PROV_HANDLE_PROP_ID,
&hProvSender,
&cbData))
{
printf("JNI: Error during CertGetCertificateContextProperty. [%d]\n", GetLastErrorLocal());
}
if (!CryptSetProvParam(hProvSender, PP_SIGNATURE_PIN, (BYTE*)sPassword, 0)){
throw "do_low_sign_hash break on CryptSetProvParam";
}
contextCache[name] = hProvSender;
// Clean up.
if(hStoreHandle)
{
CertCloseStore(hStoreHandle,0);
}
if(pCertSender)
{
CertFreeCertificateContext(pCertSender);
}
return hProvSender;
}
}
BOOL do_low_sign_hash(CERT_TYPE_PARAM &certTypeParam,BYTE * pbContent, DWORD cbContent, std::string certName, std::string password, BYTE_ARRAY * result)
{
HCRYPTHASH hHash = 0;
BYTE_ARRAY data = { pbContent, cbContent };
DWORD keySpec = AT_KEYEXCHANGE;
lanit::shared_lock_guard<lanit::shared_mutex> lock(rwMutex);
HCRYPTPROV hProv;
hProv = getSignContext2(certName, password);//getSignContext(certTypeParam.provType, certName, password);
if (!hProv){
throw "do_low_sign_hash break on acquiring signing context";
}
if (!CryptCreateHash(hProv, certTypeParam.algId, 0, 0, &hHash)){
cleanUp(hHash, data, hProv);
throw "do_low_sign_hash break on CryptCreateHash";
}
if(certTypeParam.algId == CALG_GR3411){
if (!CryptSetHashParam(hHash, HP_OID, (BYTE*)OID_HashVerbaO, 0)){
cleanUp(hHash, data, hProv);
throw "do_low_sign_hash break on CryptSetHashParam";
}
}
if (!CryptHashData(hHash, pbContent, cbContent, 0)){
cleanUp(hHash, data, hProv);
throw ("do_low_sign_hash break on CryptHashData");
}
result->size = 0;
if (!CryptSignHash(hHash, keySpec, NULL, 0, NULL, &(result->size))){
flipKeySpec(keySpec);
if (!CryptSignHash(hHash, keySpec, NULL, 0, NULL, &(result->size))){
cleanUp(hHash, data, hProv);
throw "do_low_sign_hash break on CryptSignHash";
}
}
result->blob = new BYTE[result->size];
BOOL isSuccessful = 1;
if (!CryptSignHash(hHash, keySpec, NULL, 0, result->blob, &result->size)){
isSuccessful = 0;
throw "do_low_sign_hash break on CryptSignHash final";
}
CryptDestroyHash(hHash);
//CryptReleaseContext(hProv, 0);
char messStr[1000];
sprintf(messStr,"\nCertName[%s], (%d provtype), data[%s] sign hash is: \n",certName.c_str(),certTypeParam.provType,pbContent);
printf(messStr);
if(result->blob){
int i,j,k;
for(j = 0; j < result->size; j++) {
printf("%02X", result->blob[j]);
}
printf("\n");
}
return isSuccessful;
}
Выдержка из исправленной (более новой) документации несертифицированной версии CSP RC3, следовать которой мы не вправе: "Разрешено использование только с ключевыми контейнерами, полученными ранее с помощью вызова CryptAcquireCertificatePrivateKey либо с помощью вызова CertGetCertificateContextProperty из сертификата, проверенного с помощью функции CertVerifyCertificateChainPolicy"Для выполнения требований из документации [RC3] необходимо: 1) получить ключевой контейнер при помощи функции CertGetCertificateContextProperty из сертификата или с помощью вызова CryptAcquireCertificatePrivateKey. 2) сертификат должен быть проверен с помощью функции CertVerifyCertificateChainPolicy В данном случае понятно, как выполнить требование: через [CryptAcquireCertificatePrivateKey], но при следовании документации [RC2] этот способ не является допустимым. Код выполнения требований по документации [RC3] Код:
BOOL verifyCertificateChain(PCCERT_CONTEXT pCertContext)
{ ... в реализации этой ф-ии все понятно...}
static HCRYPTPROV getSignContext2(std::string name, std::string password)
{
std::lock_guard<std::mutex> lock(exclusiveMutex);
std::map<std::string, HCRYPTPROV>::iterator it = contextCache.find(name);
LPCSTR lpszCertSubject = (LPCSTR) name.c_str();
LPCSTR sPassword = (LPCSTR) password.c_str();
HCERTSTORE hStoreHandle = 0; //
PCCERT_CONTEXT pCertSender = NULL; //
HCRYPTPROV hProvSender = 0; //
DWORD dwKeySpecSender;
// ---
char pszNameString[256];
PCCERT_CONTEXT pCertContext = NULL;
PCRYPT_KEY_PROV_INFO pData;
DWORD cbData;
DWORD dwPropId = 0;
void* pvData;
CRYPT_KEY_PROV_INFO *pCryptKeyProvInfo;
DWORD cbName;
DWORD dwKeySpec;
HCRYPTPROV hCryptProv; // CSP handle
CHAR pszName[1000];
pszName[0] = 0;
const char * stores[] = { "My" , "uMy" , "mMy", "Root" , "uRoot" , "mRoot" , "CA" , "mCA" , "uCA" , "AddressBook" , "uAddressBook" , "mAddressBook" , "SPC" , "uSPC" , "mSPC" };
DWORD cStores = 15;
printf("JNI: start function getSignContext2 name: %s password: %s\n", lpszCertSubject, sPassword);
if (it != contextCache.end())
{
HCRYPTPROV result = it->second;
printf("JNI: Get store handle. from [contextCache]\n");
return result;
}
else
{
//--------------------------------------------------------------------
for (DWORD i = 0; i < cStores; i++) {
printf("JNI: try find any certificate in [%s], use [CertOpenSystemStore] \n", stores[i]);
hStoreHandle = CertOpenSystemStore(0, stores[i]);
if(!hStoreHandle)
{
printf("JNI: Error getting store handle. [%d]\n", GetLastErrorLocal());
continue;
} else {
printf("JNI: getting store handle from: [%s]\n", stores[i]);
}
// Find the certificates in the system store.
while(pCertContext = CertEnumCertificatesInStore(hStoreHandle, pCertContext))
{
// find criptoProvider
if(!( CryptAcquireCertificatePrivateKey(
pCertContext,
0,
NULL,
&hCryptProv,
&dwKeySpec,
NULL)))
{
printf("CryptAcquireCertificatePrivateKey.\n");
}
cbName = 1000;
// Read the name of the key container.
if(CryptGetProvParam(
hCryptProv,
PP_CONTAINER,
(BYTE*)pszName,
&cbName,
0))
{
printf("CryptGetProvParam succeeded.\n");
printf("Key Container name: %s\n", pszName);
// string compare
if ( !strcmp( lpszCertSubject , pszName ) ) {
// printf("find is Successful ! \n");
break;
}
} else {
printf("Error reading key container name.\n");
}
} // end [ while(pCertContext = ... ]
// string compare
if ( !strcmp( lpszCertSubject , pszName ) ) {
printf("find is Successful ! \n");
break;
}
} // end [ for (DWORD ... ]
//--------------------------------------------------------------------
if (!verifyCertificateChain(pCertContext)){
printf("JNI: Error verifyCertificateChain [%d]\n", GetLastErrorLocal());
return 0;
}
//--------------------------------------------------------------------
if(!CryptAcquireCertificatePrivateKey(
pCertContext,
0,
NULL,
&hProvSender,
&dwKeySpecSender,
NULL))
{
printf("JNI: Error during CryptAcquireCertificatePrivateKey. [%d]\n", GetLastErrorLocal());
}
if (!CryptSetProvParam(hProvSender, PP_SIGNATURE_PIN, (BYTE*)sPassword, 0)){
printf("JNI: do_low_sign_hash break on CryptSetProvParam [%d]\n", GetLastErrorLocal());
// cleanUp(hHash, data);
return 0;
}
contextCache[name] = hProvSender;
// Clean up.
if(hStoreHandle)
{
CertCloseStore(hStoreHandle,0);
}
if(pCertSender)
{
CertFreeCertificateContext(pCertSender);
}
return hProvSender;
}
}
BOOL do_low_sign_hash(CERT_TYPE_PARAM &certTypeParam,BYTE * pbContent, DWORD cbContent, std::string certName, std::string password, BYTE_ARRAY * result)
{
HCRYPTHASH hHash = 0;
BYTE_ARRAY data = { pbContent, cbContent };
DWORD keySpec = AT_KEYEXCHANGE;
lanit::shared_lock_guard<lanit::shared_mutex> lock(rwMutex);
HCRYPTPROV hProv;
try {
hProv = getSignContext2(certName, password);//getSignContext(certTypeParam.provType, certName, password);
if (!hProv){
printf("JNI: do_low_sign_hash break on acquiring signing context \n");
//cleanUp(hHash, data);
return 0;
}
if (!CryptCreateHash(hProv, CALG_GR3411, 0, 0, &hHash)){
printf("JNI: do_low_sign_hash break on CryptCreateHash [%d]\n", GetLastErrorLocal());
cleanUp(hHash, data, hProv);
return 0;
}
if (!CryptSetHashParam(hHash, HP_OID, (BYTE*)OID_HashVerbaO, 0)){
printf("JNI: do_low_sign_hash break on CryptSetHashParam [%d]\n", GetLastErrorLocal());
cleanUp(hHash, data, hProv);
return 0;
}
if (!CryptHashData(hHash, pbContent, cbContent, 0)){
printf("JNI: do_low_sign_hash break on CryptHashData [%d]\n", GetLastErrorLocal());
cleanUp(hHash, data, hProv);
return 0;
}
result->size = 0;
if (!CryptSignHash(hHash, keySpec, NULL, 0, NULL, &(result->size))){
flipKeySpec(keySpec);
if (!CryptSignHash(hHash, keySpec, NULL, 0, NULL, &(result->size))){
printf("JNI: do_low_sign_hash break on CryptSignHash [%d]\n", GetLastErrorLocal());
cleanUp(hHash, data, hProv);
return 0;
}
}
result->blob = new BYTE[result->size];
BOOL isSuccessful = 1;
if (!CryptSignHash(hHash, keySpec, NULL, 0, result->blob, &result->size)){
isSuccessful = 0;
printf("JNI: do_low_sign_hash break on CryptSignHash final [%d]\n", GetLastErrorLocal());
}
CryptDestroyHash(hHash);
//CryptReleaseContext(hProv, 0);
return isSuccessful;
} catch (std::exception *e) {
printf((*e).what());
cleanUp(hHash, data, hProv);
return 0;
}
}
Просьба пояснить, как нужно написать код, ОСТАВАЯСЬ СТРОГО В РАМКАХ требований к использовании функции CryptSignHash из документации к CSP RC2?
Если это технически невозможно (например, в документации RC2 ошибка), какие существуют варианты ? Ведь проблема в том, что данный релиз - последний, сертифицированный на данный момент.Отредактировано пользователем 11 декабря 2017 г. 18:14:15(UTC)
| Причина: Не указана
|