
main.zip
(2kb) загружен 1 раз(а).Вопрос актуальный.
Примеры проверки подписи от КриптоПРО тоже не работают с включенным флагом
StrengthenedKeyUsageControl=1
Расширенный тест по мотивам примеров от КриптоПРО:
#include <stdio.h>
#ifdef _WIN32
# include <windows.h>
# include <wincrypt.h>
# include <tchar.h>
#else
# include <string.h>
# include <stdlib.h>
# include <CSP_WinDef.h>
# include <CSP_WinCrypt.h>
# include "reader/tchar.h"
#endif
#include <WinCryptEx.h>
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
const char * CONTAINER_NAME = "\\\\.\\HDIMAGE\\test6";
const char * CONTAINER_PIN = "12345678";
const DWORD KEY_USAGE = AT_SIGNATURE;
static void handle_error(char *s);
static void cleanup(void);
static DWORD dwSigLen = 0;
static BYTE *pbSignature = NULL;
static DWORD dwBlobLen = 0;
static BYTE *pbKeyBlob = NULL;
static BYTE *pbSigningData = NULL;
static DWORD dwSigningDataSize = 1024;
static DWORD dwCertLen = 0;
static BYTE *pbCertificate = NULL;
static void prepare() {
pbSigningData = (BYTE *)malloc(dwSigningDataSize);
memset(pbSigningData, 0, dwSigningDataSize);
}
static void export_key(HCRYPTPROV hProv) {
HCRYPTKEY hKey = 0;
if (CryptGetUserKey(hProv, AT_SIGNATURE, &hKey)) {
if(CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen)) {
pbKeyBlob = (BYTE*)malloc(dwBlobLen);
if(!CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, pbKeyBlob, &dwBlobLen))
handle_error("CryptExportKey");
} else
handle_error("CryptExportKey, get size");
if(CryptGetKeyParam(hKey, KP_CERTIFICATE, NULL, &dwCertLen, 0)) {
pbCertificate = (BYTE*)malloc(dwCertLen);
if(!CryptGetKeyParam(hKey, KP_CERTIFICATE, pbCertificate, &dwCertLen, 0))
handle_error("CryptGetKeyParam, certificate");
} else
handle_error("CryptGetKeyParam, get certificate size");
}
if(hKey)
CryptDestroyKey(hKey);
}
static bool sign() {
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
bool result = false;
printf("Создание цифровой подписи...\n");
if (CryptAcquireContext(&hProv, CONTAINER_NAME, NULL, PROV_GOST_2012_512, CRYPT_SILENT)) {
if (CryptSetProvParam(hProv, PP_SIGNATURE_PIN, (const BYTE *)CONTAINER_PIN, 0)) {
export_key(hProv);
if(CryptCreateHash(hProv, CALG_GR3411_2012_256, 0, 0, &hHash)) {
if(CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, NULL, &dwSigLen)) {
pbSignature = (BYTE *)malloc(dwSigLen);
if(CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSignature, &dwSigLen))
printf("Подписание выполнено успешно\n");
else
handle_error("CryptSignHash");
} else
handle_error("Signature length");
result = true;
} else
handle_error("CryptCreateHash");
} else
handle_error("CryptSetProvParam");
} else
handle_error("CryptAcquireContext");
if(hHash)
CryptDestroyHash(hHash);
if(hProv)
CryptReleaseContext(hProv, 0);
return result;
}
void validate_with_container() {
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
HCRYPTKEY hKey = 0;
bool result = false;
printf("Проверка сигнатуры с публичным ключом расположенном в контейнере...\n");
if (CryptAcquireContext(&hProv, CONTAINER_NAME, NULL, PROV_GOST_2012_512, CRYPT_SILENT)) {
if (CryptSetProvParam(hProv, PP_SIGNATURE_PIN, (const BYTE *)CONTAINER_PIN, 0)) {
if (CryptGetUserKey(hProv, AT_SIGNATURE, &hKey)) {
if(CryptCreateHash(hProv, CALG_GR3411_2012_256, 0, 0, &hHash)) {
if(CryptVerifySignature(hHash, pbSignature, dwSigLen, hKey, NULL, 0))
printf("Проверка прошла успешно\n");
else
handle_error("Ошибка при проверке подписи. *******!!!!! CryptVerifySignature");
} else
handle_error("CryptCreateHash");
} else
handle_error("CryptGetUserKey");
} else
handle_error("CryptSetProvParam");
} else
handle_error("CryptAcquireContext");
if(hHash)
CryptDestroyHash(hHash);
if(hKey)
CryptDestroyKey(hKey);
if(hProv)
CryptReleaseContext(hProv, 0);
}
void validate_with_external_key() {
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
HCRYPTKEY hPubKey = 0;
bool result = false;
printf("Проверка сигнатуры с импортированным публичным ключом...\n");
if (CryptAcquireContext(&hProv, NULL, NULL, PROV_GOST_2012_512, CRYPT_VERIFYCONTEXT)) {
if(CryptImportKey(hProv, pbKeyBlob, dwBlobLen, 0, 0, &hPubKey)) {
/* Возможно надо дополнить ключ сертификатом? */
if (pbCertificate)
if(!CryptSetKeyParam(hPubKey, KP_CERTIFICATE, pbCertificate, dwCertLen))
handle_error("CryptSetKeyParam KP_CERTIFICATE");
if(CryptCreateHash(hProv, CALG_GR3411_2012_256, 0, 0, &hHash)) {
if(CryptVerifySignature(hHash, pbSignature, dwSigLen, hPubKey, NULL, 0))
printf("Проверка прошла успешно\n");
else
handle_error("Ошибка при проверке подписи. *******!!!!! CryptVerifySignature");
} else
handle_error("CryptCreateHash");
} else
handle_error("CryptImportKey");
} else
handle_error("CryptAcquireContext");
if(hHash)
CryptDestroyHash(hHash);
if(hPubKey)
CryptDestroyKey(hPubKey);
if(hProv)
CryptReleaseContext(hProv, 0);
}
void done() {
if(pbSignature)
free(pbSignature);
if(pbKeyBlob)
free(pbKeyBlob);
if (pbSigningData)
free(pbSigningData);
if (pbCertificate)
free(pbCertificate);
pbCertificate = 0;
pbSignature = 0;
pbKeyBlob = 0;
pbSigningData = 0;
printf("Done\n");
}
int main(void) {
prepare();
if (sign()) {
printf("\n");
validate_with_container();
printf("\n");
validate_with_external_key();
}
done();
}
void handle_error(char *s)
{
DWORD err = GetLastError();
printf("Ошибка : 0x%x (%s)\n", err, s);
}
sudo /opt/cprocsp/sbin/amd64/cpconfig -ini '\config\parameters' -add long StrengthenedKeyUsageControl 0
Результат запуска теста:
Создание цифровой подписи...
Подписание выполнено успешно
Проверка сигнатуры с публичным ключом расположенном в контейнере...
Проверка прошла успешно
Проверка сигнатуры с импортированным публичным ключом...
Ошибка : 0x80090020 (CryptSetKeyParam KP_CERTIFICATE)
Проверка прошла успешно
Done
sudo /opt/cprocsp/sbin/amd64/cpconfig -ini '\config\parameters' -add long StrengthenedKeyUsageControl 1
Результат запуска теста:
Результат запуска теста:
Создание цифровой подписи...
Подписание выполнено успешно
Проверка сигнатуры с публичным ключом расположенном в контейнере...
Проверка прошла успешно
Проверка сигнатуры с импортированным публичным ключом...
Ошибка : 0x80090020 (CryptSetKeyParam KP_CERTIFICATE)
Ошибка : 0x80090015 (Ошибка при проверке подписи. *******!!!!! CryptVerifySignature)
Done
Я попытался импортировать сертификат ключей вместе с ключом, полагая, что все данные для проверки приватного ключа есть в расширении сертификата, увы... безуспешно.