Retired Microsoft Blog disclaimer

This directory is a mirror of retired "Decrypt My World" MSDN blog and is provided as is. All posting authorship and copyrights belong to respective authors.
Original URL: https://blogs.msdn.microsoft.com/alejacma/2008/01/23/how-to-sign-and-verify-with-cryptoapi-and-a-user-certificate/
Post name: How to sign and verify with CryptoAPI and a user certificate
Original author: Alejandro Campos Magencio
Posting date: 2008-01-23T06:35:00+00:00


Hi, welcome back,


Today I will show how to sign data and verify that signature using CryptoAPI and a certificate from our Personal store. The comments in the code should help to understand it. Remember that this is just a sample, and some more cleanup would be needed incase of error, for instance.


<SAMPLE>

// Includes
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <wincrypt.h>

// Defines
#define CERT_PERSONAL_STORE_NAME L"My"
#define CERT_OTHER_PEOPLE_STORE_NAME L"AddressBook"
#define MY_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
#define BUFSIZE 1024

// Local functions
void Sign(wchar_t * SignerName, wchar_t * DataFileName, wchar_t * SignatureFileName);
void Verify(wchar_t * SignerName, wchar_t * SignatureFileName, wchar_t * DataFileName);

// ShowUsageAndExit
void ShowUsageAndExit()
{
wprintf(L"Usage:\n");
wprintf(L" - To sign: SignVerify s signer_name data_file signature_file\n");
wprintf(L" - To verify: SignVerify v signer_name data_file signature_file\n");
wprintf(L"\n<< Press any key to continue >>\n");
_getch();
exit(1);

}
// End of ShowUsageAndExit

// CheckError
void CheckError(BOOL condition, wchar_t * message)
{
wprintf(message);
if (condition)
{
wprintf(L"SUCCESS\n");
}
else
{
// TODO: Some cleanup
wprintf(L"FAILURE (0x%x)\n", GetLastError());
wprintf(L"\n<< Press any key to continue >>\n");
_getch();
exit(1);
}
}
// End CheckError

// Main
void wmain(int argc, wchar_t * argv[])
{

// Usage
if (argc != 5) {
ShowUsageAndExit();
}

if (!wcscmp(argv[1], L"s"))
{
// Sign
Sign(argv[2], argv[3], argv[4]);
}
else if (!wcscmp(argv[1], L"v"))
{
// Verify
Verify(argv[2], argv[3], argv[4]);
}
else
{
// Error
ShowUsageAndExit();
}

// The end
wprintf(L"\n<< Press any key to continue >>\n");
_getch();

}
// End of main

// Sign
void Sign(wchar_t * SignerName, wchar_t * DataFileName, wchar_t * SignatureFileName)
{
// Variables
HCERTSTORE hStoreHandle = NULL;
PCCERT_CONTEXT pSignerCert = NULL;
HCRYPTPROV hCryptProv = NULL;
DWORD dwKeySpec = 0;
HCRYPTHASH hHash = NULL;
HANDLE hDataFile = NULL;
BOOL bResult = FALSE;
BYTE rgbFile[BUFSIZE];
DWORD cbRead = 0;
DWORD dwSigLen = 0;
BYTE * pbSignature = NULL;
HANDLE hSignatureFile = NULL;
DWORD lpNumberOfBytesWritten = 0;

wprintf(L"SIGNING\n\n");

// Open the certificate store.
hStoreHandle = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
CERT_PERSONAL_STORE_NAME
);
CheckError((BOOL)hStoreHandle, L"CertOpenStore....................... ");

// Get signer's certificate with access to private key.
do {
// Get a certificate that matches the search criteria
pSignerCert = CertFindCertificateInStore(
hStoreHandle,
MY_TYPE,
0,
CERT_FIND_SUBJECT_STR,
SignerName,
pSignerCert
);
CheckError((BOOL)pSignerCert, L"CertFindCertificateInStore.......... ");

// Get the CSP, and check if we can sign with the private key
bResult = CryptAcquireCertificatePrivateKey(
pSignerCert,
0,
NULL,
&hCryptProv,
&dwKeySpec,
NULL
);
CheckError(bResult, L"CryptAcquireCertificatePrivateKey... ");

} while ((dwKeySpec & AT_SIGNATURE) != AT_SIGNATURE);

// Create the hash object.
bResult = CryptCreateHash(
hCryptProv,
CALG_MD5,
0,
0,
&hHash
);
CheckError(bResult, L"CryptCreateHash..................... ");

// Open the file with the content to be signed
hDataFile = CreateFileW(DataFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
);
CheckError((hDataFile != INVALID_HANDLE_VALUE), L"CreateFile.......................... ");

// Compute the cryptographic hash of the data.
while (bResult = ReadFile(hDataFile, rgbFile, BUFSIZE, &cbRead, NULL))
{
if (cbRead == 0)
{
break;
}
CheckError(bResult, L"ReadFile............................ ");

bResult = CryptHashData(
hHash,
rgbFile,
cbRead,
0
);
CheckError(bResult, L"CryptHashData....................... ");

}
CheckError(bResult, L"ReadFile............................ ");

// Sign the hash object
dwSigLen = 0;
bResult = CryptSignHash(
hHash,
AT_SIGNATURE,
NULL,
0,
NULL,
&dwSigLen
);
CheckError(bResult, L"CryptSignHash....................... ");

pbSignature = (BYTE *)malloc(dwSigLen);
CheckError((BOOL)pbSignature, L"malloc.............................. ");

bResult = CryptSignHash(
hHash,
AT_SIGNATURE,
NULL,
0,
pbSignature,
&dwSigLen
);
CheckError(bResult, L"CryptSignHash....................... ");

// Create a file to save the signature
hSignatureFile = CreateFileW(
SignatureFileName,
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
CheckError((hSignatureFile != INVALID_HANDLE_VALUE), L"CreateFile.......................... ");

// Write the signature to the file
bResult = WriteFile(
hSignatureFile,
(LPCVOID)pbSignature,
dwSigLen,
&lpNumberOfBytesWritten,
NULL
);
CheckError(bResult, L"WriteFile........................... ");

// Clean up and free memory.
free(pbSignature);

CloseHandle(hDataFile);
CloseHandle(hSignatureFile);

bResult = CryptDestroyHash(hHash);
CheckError(bResult, L"CryptDestroyHash.................... ");

bResult = CertFreeCertificateContext(pSignerCert);
CheckError(bResult, L"CertFreeCertificateContext.......... ");

bResult = CertCloseStore(
hStoreHandle,
CERT_CLOSE_STORE_CHECK_FLAG
);
CheckError(bResult, L"CertCloseStore...................... ");

}
// End of Sign

// Verify
void Verify(wchar_t * SignerName, wchar_t * DataFileName, wchar_t * SignatureFileName)
{
// Variables
HCERTSTORE hStoreHandle = NULL;
PCCERT_CONTEXT pSignerCert = NULL;
DWORD dwKeySpec = 0;
HCRYPTPROV hCryptProv = NULL;
HCRYPTHASH hHash = NULL;
HANDLE hDataFile = NULL;
BOOL bResult = FALSE;
BYTE rgbFile[BUFSIZE];
DWORD cbRead = 0;
HANDLE hSignatureFile = NULL;
BYTE * pbBinary = NULL;
DWORD cbBinary = 0;
HCRYPTKEY hPubKey = NULL;

wprintf(L"VERIFYING\n\n");

// Open the certificate store.
hStoreHandle = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
CERT_PERSONAL_STORE_NAME
);
CheckError((BOOL)hStoreHandle, L"CertOpenStore....................... ");

// Get a certificate that matches the search criteria
pSignerCert = CertFindCertificateInStore(
hStoreHandle,
MY_TYPE,
0,
CERT_FIND_SUBJECT_STR,
SignerName,
pSignerCert
);
CheckError((BOOL)pSignerCert, L"CertFindCertificateInStore.......... ");

// Get the CSP
bResult = CryptAcquireContext(
&hCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT
);
CheckError(bResult, L"CryptAcquireContext................. ");

// Create the hash object.
bResult = CryptCreateHash(
hCryptProv,
CALG_MD5,
0,
0,
&hHash
);
CheckError(bResult, L"CryptCreateHash..................... ");

// Open the file with the content that was signed.
hDataFile = CreateFileW(
DataFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
);
CheckError((hDataFile != INVALID_HANDLE_VALUE), L"CreateFile.......................... ");

// Compute the cryptographic hash of the data.
while (bResult = ReadFile(hDataFile, rgbFile, BUFSIZE, &cbRead, NULL))
{
if (cbRead == 0)
{
break;
}
CheckError(bResult, L"ReadFile............................ ");

bResult = CryptHashData(
hHash,
rgbFile,
cbRead,
0
);
CheckError(bResult, L"CryptHashData....................... ");
}
CheckError(bResult, L"ReadFile............................ ");

// Open the file with the signature
hSignatureFile = CreateFileW(
SignatureFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
);
CheckError((hSignatureFile != INVALID_HANDLE_VALUE), L"CreateFile.......................... ");

// Read the signature from the file
pbBinary = (BYTE *)malloc(BUFSIZE);
CheckError((BOOL)pbBinary, L"malloc.............................. ");

bResult = ReadFile(hSignatureFile, pbBinary, BUFSIZE, &cbBinary, NULL);
CheckError(bResult, L"ReadFile............................ ");

// Get the public key from the certificate
CryptImportPublicKeyInfo(
hCryptProv,
MY_TYPE,
&pSignerCert->pCertInfo->SubjectPublicKeyInfo,
&hPubKey
);
CheckError(bResult, L"CryptImportPublicKeyInfo............ ");

// Verify the signature
bResult = CryptVerifySignature(
hHash,
pbBinary,
cbBinary,
hPubKey,
NULL,
0
);
CheckError(bResult, L"CryptVerifySignature................ ");

// Clean up and free memory.
free(pbBinary);

CloseHandle(hDataFile);
CloseHandle(hSignatureFile);

bResult = CryptDestroyHash(hHash);
CheckError(bResult, L"CryptDestroyHash.................... ");

bResult = CertFreeCertificateContext(pSignerCert);
CheckError(bResult, L"CertFreeCertificateContext.......... ");

bResult = CertCloseStore(
hStoreHandle,
CERT_CLOSE_STORE_CHECK_FLAG
);
CheckError(bResult, L"CertCloseStore...................... ");

bResult = CryptReleaseContext(
hCryptProv,
0
);
CheckError(bResult, L"CryptReleaseContext................. ");
}
// End of Verify


</SAMPLE>



I hope this helps.


Cheers,



Alex (Alejandro Campos Magencio)


Share this article:

Comments:

Comments are closed.