Click here to Skip to main content
13,087,566 members (95,109 online)
Click here to Skip to main content
Add your own
alternative version

Tagged as


3 bookmarked
Posted 5 Nov 2010

How to Use Certificate from Disk with Microsoft CryptoAPI

, 5 Nov 2010
Rate this:
Please Sign up or sign in to vote.
How to use certificate from disk with Microsoft CryptoAPI

This article describes how to digitally sign data using a certificate which is stored outside the Windows Certificate Store. So it may be distributed as external file or is hardcoded into your application.

The provided code samples are for demonstration purposes only and are not intended to be used in a production system - you should at least add proper error handling and release allocated memory.

Preparing key-pair with Self-signed Certificate

A key-pair can be generated using the OpenSSL. A list of commands used for generation follows, many special articles with details on how to generate certificate can be found on the internet, so I don't mention any details about it here. On the projects website, you can also find links to binaries for the appropriate platform.

  • Generate private key of desired length (1024 bits):
    openssl genrsa -des3 -out server.key 1024
  • Create request for self-signed certificate:
    openssl req -new -key server.key -out server.csr
  • Remove password from the private key:
    openssl rsa -in server.key -out server2.key
  • Self-sign the certificate request (-days is expiration in days):
    openssl x509 -req -days 365 -in server.csr -signkey server2.key -out server.crt
  • Convert output to PKCS#12 format which we can use in code (-keysig parameter allows us to use key-pair for signing):
    openssl pkcs12 -export -in server.crt -inkey server2.key –keysig -out c:\mykey.p12

Signing Data

The final solution is quite easy as you can see in the code below. The only important thing is that your key-pair must be saved in PKCS#12 form (.p12 extension).


// load key-pair from disk to memory. This can be quite
// easily changed to have key-pair hardcoded
FILE *fIn = fopen("C:\\mykey.p12", "rb");
fseek(fIn, 0, SEEK_END);
data.cbData = ftell(fIn);
fseek(fIn, 0, SEEK_SET);
data.pbData = (BYTE *)malloc(pData.cbData);
fread(data.pbData, 1, pData.cbData, fIn);

// Convert key-pair data to the in-memory certificate store
// If the P12 file is protected with a password, pass it to
// the function    
HCERTSTORE hCertStore = PFXImportCertStore(&data, L"P12ExportPassword", 0);

// If in-memory certificate store wasn't initialized, try
// empty password (NULL has different meaning than empty string)
if (!hCertStore)
  hCertStore = PFXImportCertStore(&data, L"", 0);
if (!hCertStore)
  hCertStore = PFXImportCertStore(&data, NULL, 0);

// Find the certificate in P12 file (we expect there is only one)    
PCCERT_CONTEXT hContext = CertFindCertificateInStore

BOOL bFreeHandle;
DWORD dwKeySpec;
// acquire private key to this certificate, returned hProv handle must be closed
// if bFreeHandle is TRUE    
BOOL bResult = CryptAcquireCertificatePrivateKey
    (hContext, 0, NULL, &hProv, &dwKeySpec, &bFreeHandle);

const char szBuffToSign[] = "Hello world!";    
DWORD dwSize = 0;

And now, based on our needs sign data as a message, which allows us to include selected certificates:

memset(&p, 0, sizeof(CRYPT_SIGN_MESSAGE_PARA));
p.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);
p.dwMsgEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
p.pSigningCert = hContext;
p.HashAlgorithm.pszObjId = szOID_OIWSEC_sha1;
p.cMsgCert = 1;
p.rgpMsgCert = &hContext;
DWORD dwSizes[] = {

const BYTE *byMessageArray[] = { 
                    (const BYTE *) szBuffToSign

bResult = CryptSignMessage(&p, FALSE, 1, byMessageArray,  dwSizes, NULL, &dwSize);
BYTE *pBuff = (BYTE *) malloc(dwSize);
memset(pBuff, 0, dwSize);
bResult = CryptSignMessage(&p, FALSE, 1, byMessageArray, dwSizes, pBuff, &dwSize);

Or generate a hash from data and sign this hash:

CryptCreateHash(hProv, CALG_SHA1, NULL, 0, &hHash);
CryptHashData(hHash, (const BYTE *)szBuffToSign, strlen(szBuffToSign), 0);    
CryptSignHash(hHash, AT_SIGNATURE, "", 0, NULL, &dwSize);

BYTE *pBuff = (BYTE *) malloc(dwSize);
memset(pBuff, 0, dwSize);
CryptSignHash(hHash, AT_SIGNATURE, "", 0, pBuff, &dwSize);



This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Team Leader NCR
Czech Republic Czech Republic
I'm software developer since 1996. I started with assembler on Intel 8051 CPUs, during years I was interested in C, C++, Sybase PowerBuilder, PHP, Sybase Anywhere Database, MSSQL server and multiplatform development.

Currently I'm developing in C++ and C# (this is my favorit and I spent some time with MCPD achievement). I'm also interested in design patterns.

You may also be interested in...


Comments and Discussions

QuestionComplete code for this article? Pin
Member 1163332722-Apr-15 4:47
memberMember 1163332722-Apr-15 4:47 
AnswerRe: Complete code for this article? Pin
voloda222-Apr-15 9:35
membervoloda222-Apr-15 9:35 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.170813.1 | Last Updated 5 Nov 2010
Article Copyright 2010 by voloda2
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid