Статус: Сотрудник
Группы: Администраторы, Участники Зарегистрирован: 16.04.2008(UTC) Сообщений: 1,464
Сказал(а) «Спасибо»: 40 раз Поблагодарили: 588 раз в 409 постах
|
День добрый. Это её реализация. Половины функций не хватает, но должно быть понятно. Код:static int do_sign(TCHAR *infile, TCHAR *certfile, TCHAR *outfile, int detached,
LPCSTR hash_oid, int include, int req_compliant, BOOL base64,
int Cert_LM, DWORD dwCadesFlags, BOOL bAddSigTime, PCSTR szPIN, DWORD dwFlags)
{
PCCERT_CONTEXT pUserCert = NULL;
PCCERT_CONTEXT pMemoryCert = NULL;
int ret = ERROR_INTERNAL_ERROR;
BOOL bResult;
DWORD dwErrFn;
BYTE *mem_tbs = NULL;
DWORD mem_len = 0;
CRYPT_SIGN_MESSAGE_PARA param;
DWORD MessageSizeArray[1];
const BYTE *MessageArray[1];
DWORD signed_len = 0;
BYTE *signed_mem = NULL;
char errtxt[100];
HCRYPTPROV hCryptProv = 0;
DWORD keytype = 0;
BOOL should_release_ctx = FALSE;
CRYPT_ATTR_BLOB cablob[1];
CRYPT_ATTRIBUTE ca[1];
LPBYTE pbAuth = NULL;
DWORD cbAuth = 0;
FILETIME fileTime;
SYSTEMTIME systemTime;
if (!certfile) {
DebugErrorFL("No user certificate specified.");
goto err;
}
if (!infile) {
DebugErrorFL("No input file was specified.");
goto err;
}
pUserCert = read_cert_from_my(certfile, Cert_LM);
if (!pUserCert) {
sprintf(errtxt, "Cannot find User certificate: " _T2A, certfile);
DebugErrorFL(errtxt);
goto err;
}
if (req_compliant) {
if (verify_certificate_chain(pUserCert)) {
DebugErrorFL("Certificate chain verify failed.");
goto err;
}
else {
_tprintf(_TEXT("Certificate chain validation succeed.\n\n"));
}
}
dwErrFn = SetCertPin(pUserCert, szPIN, &pMemoryCert);
if (dwErrFn) {
ret = dwErrFn;
goto err;
}
if (pUserCert) {
CertFreeCertificateContext(pUserCert);
}
pUserCert = pMemoryCert;
dwFlags |= CRYPT_ACQUIRE_COMPARE_KEY_FLAG;
bResult = CryptAcquireCertificatePrivateKey(
pUserCert,
dwFlags,
NULL,
&hCryptProv,
&keytype,
&should_release_ctx);
if (!bResult) {
ret = DebugErrorFL("Cryptographic context could not be acquired.");
goto err;
}
if (!get_file_data_pointer(infile, &mem_len, &mem_tbs)) {
DebugErrorFL("Cannot open input file.");
goto err;
}
if (!hash_oid)
hash_oid = GetDefaultHashOID(pUserCert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
// Обязательно нужно обнулить все поля структуры,
// иначе это может привести к access violation в функциях CryptoAPI.
// В примере из MSDN это отсутствует.
ZeroMemory(¶m, sizeof(CRYPT_SIGN_MESSAGE_PARA));
param.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);
param.dwMsgEncodingType = TYPE_DER;
param.pSigningCert = pUserCert;
param.HashAlgorithm.pszObjId = (LPSTR)hash_oid;
param.HashAlgorithm.Parameters.cbData = 0;
param.HashAlgorithm.Parameters.pbData = NULL;
param.pvHashAuxInfo = NULL;
param.cMsgCert = include; /* включаем сертификат отправителя если попросили*/
param.rgpMsgCert = &pUserCert;
param.cAuthAttr = 0;
param.dwInnerContentType = 0;
param.cMsgCrl = 0;
param.cUnauthAttr = 0;
GetSystemTime(&systemTime);
SystemTimeToFileTime(&systemTime, &fileTime);
bResult = CryptEncodeObject(TYPE_DER,
szOID_RSA_signingTime,
(LPVOID)&fileTime,
NULL,
&cbAuth);
if (!bResult) {
ret = DebugErrorFL("Cannot encode object");
goto err;
}
pbAuth = (BYTE*)malloc(cbAuth);
if (!pbAuth) {
ret = DebugCodeFL(ERROR_NOT_ENOUGH_MEMORY, "Out of memory");
goto err;
}
bResult = CryptEncodeObject(TYPE_DER,
szOID_RSA_signingTime,
(LPVOID)&fileTime,
pbAuth,
&cbAuth);
if (!bResult) {
ret = DebugErrorFL("Cannot encode object");
goto err;
}
cablob[0].cbData = cbAuth;
cablob[0].pbData = pbAuth;
ca[0].pszObjId = szOID_RSA_signingTime;
ca[0].cValue = 1;
ca[0].rgValue = cablob;
if (bAddSigTime) {
param.cAuthAttr = 1;
param.rgAuthAttr = ca;
}
param.dwFlags = dwCadesFlags;
MessageArray[0] = mem_tbs;
MessageSizeArray[0] = mem_len;
printf ("Source message length: %lu\n", (unsigned long)mem_len);
bResult = CryptSignMessage(
¶m,
detached,
1,
MessageArray,
MessageSizeArray,
NULL,
&signed_len);
if (bResult) {
printf("Calculated signature (or signed message) length: %lu\n", (unsigned long)signed_len);
signed_mem = (BYTE*) malloc(signed_len);
if (!signed_mem) {
ret = DebugCodeFL(ERROR_NOT_ENOUGH_MEMORY, "Out of memory");
goto err;
}
}
else {
ret = DebugErrorFL("Signature creation error");
goto err;
}
bResult = CryptSignMessage(
¶m,
detached,
1,
MessageArray,
MessageSizeArray,
signed_mem,
&signed_len);
if (bResult) {
printf("Signature was done. Signature (or signed message) length: %lu\n", (unsigned long)signed_len);
}
else {
ret = DebugErrorFL("Signature creation error");
goto err;
}
if (outfile) {
ret = write_binary_file(outfile, signed_len, signed_mem, base64);
goto err;
}
if (req_compliant) {
_tprintf(_TEXT("\nSignature of file (%s) was created using key tied with certificate:\n\n"), infile);
PrintCertInfo(pUserCert);
if (outfile) {
_tprintf(_TEXT("\nSignature was saved in file (%s).\n\n"), outfile ? outfile : _TEXT("NULL"));
}
}
ret = ERROR_SUCCESS;
err:
if (pUserCert) {
CertFreeCertificateContext(pUserCert);
}
if (should_release_ctx)
CryptReleaseContext(hCryptProv, 0);
free(signed_mem);
free(pbAuth);
release_file_data_pointer(mem_tbs);
return ret;
}
|
 1 пользователь поблагодарил Русев Андрей за этот пост.
|
|