Original URL: | https://blogs.msdn.microsoft.com/alejacma/2009/03/16/how-to-create-a-self-signed-certificate-with-cryptoapi-c/ |
Post name: | How to create a self-signed certificate with CryptoAPI (C++) |
Original author: | Alejandro Campos Magencio |
Posting date: | 2009-03-16T08:36:00+00:00 |
Hi all,
The following C++ sample shows how to use CertCreateSelfSignCertificate API to create a self-signed certificate. The private/public key pair will be created in the machine profile and the certificate will be stored in the Trusted Root CA store of that same profile:
#include "stdio.h"
#include "conio.h"
#include "windows.h"
#include "wincrypt.h"
#include "tchar.h"
int SelfSignedCertificateTest()
{
// CREATE KEY PAIR FOR SELF-SIGNED CERTIFICATE IN MACHINE PROFILEHCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = NULL;__try
{
// Acquire key container
_tprintf(_T("CryptAcquireContext... "));
if (!CryptAcquireContext(&hCryptProv, _T("alejacma"), NULL, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET))
{
// Error
_tprintf(_T("Error 0x%x\n"), GetLastError());// Try to create a new key container
_tprintf(_T("CryptAcquireContext... "));
if (!CryptAcquireContext(&hCryptProv, _T("alejacma"), NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_MACHINE_KEYSET))
{
// Error
_tprintf(_T("Error 0x%x\n"), GetLastError());
return 0;
}
else
{
_tprintf(_T("Success\n"));
}
}
else
{
_tprintf(_T("Success\n"));
}// Generate new key pair
_tprintf(_T("CryptGenKey... "));
if (!CryptGenKey(hCryptProv, AT_SIGNATURE, 0x08000000 /*RSA-2048-BIT_KEY*/, &hKey))
{
// Error
_tprintf(_T("Error 0x%x\n"), GetLastError());
return 0;
}
else
{
_tprintf(_T("Success\n"));
}
}
__finally
{
// Clean upif (hKey)
{
_tprintf(_T("CryptDestroyKey... "));
CryptDestroyKey(hKey);
_tprintf(_T("Success\n"));
}
if (hCryptProv)
{
_tprintf(_T("CryptReleaseContext... "));
CryptReleaseContext(hCryptProv, 0);
_tprintf(_T("Success\n"));
}
}// CREATE SELF-SIGNED CERTIFICATE AND ADD IT TO ROOT STORE IN MACHINE PROFILE
PCCERT_CONTEXT pCertContext = NULL;
BYTE *pbEncoded = NULL;
HCERTSTORE hStore = NULL;
HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProvOrNCryptKey = NULL;
BOOL fCallerFreeProvOrNCryptKey = FALSE;__try
{
// Encode certificate Subject
LPCTSTR pszX500 = _T("CN=Alejacma, T=Test");
DWORD cbEncoded = 0;
_tprintf(_T("CertStrToName... "));
if (!CertStrToName(X509_ASN_ENCODING, pszX500, CERT_X500_NAME_STR, NULL, pbEncoded, &cbEncoded, NULL))
{
// Error
_tprintf(_T("Error 0x%x\n"), GetLastError());
return 0;
}
else
{
_tprintf(_T("Success\n"));
}_tprintf(_T("malloc... "));
if (!(pbEncoded = (BYTE *)malloc(cbEncoded)))
{
// Error
_tprintf(_T("Error 0x%x\n"), GetLastError());
return 0;
}
else
{
_tprintf(_T("Success\n"));
}_tprintf(_T("CertStrToName... "));
if (!CertStrToName(X509_ASN_ENCODING, pszX500, CERT_X500_NAME_STR, NULL, pbEncoded, &cbEncoded, NULL))
{
// Error
_tprintf(_T("Error 0x%x\n"), GetLastError());
return 0;
}
else
{
_tprintf(_T("Success\n"));
}// Prepare certificate Subject for self-signed certificate
CERT_NAME_BLOB SubjectIssuerBlob;
memset(&SubjectIssuerBlob, 0, sizeof(SubjectIssuerBlob));
SubjectIssuerBlob.cbData = cbEncoded;
SubjectIssuerBlob.pbData = pbEncoded;// Prepare key provider structure for self-signed certificate
CRYPT_KEY_PROV_INFO KeyProvInfo;
memset(&KeyProvInfo, 0, sizeof(KeyProvInfo));
KeyProvInfo.pwszContainerName = _T("alejacma");
KeyProvInfo.pwszProvName = NULL;
KeyProvInfo.dwProvType = PROV_RSA_FULL;
KeyProvInfo.dwFlags = CRYPT_MACHINE_KEYSET;
KeyProvInfo.cProvParam = 0;
KeyProvInfo.rgProvParam = NULL;
KeyProvInfo.dwKeySpec = AT_SIGNATURE;// Prepare algorithm structure for self-signed certificate
CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm;
memset(&SignatureAlgorithm, 0, sizeof(SignatureAlgorithm));
SignatureAlgorithm.pszObjId = szOID_RSA_SHA1RSA;// Prepare Expiration date for self-signed certificate
SYSTEMTIME EndTime;
GetSystemTime(&EndTime);
EndTime.wYear += 5;// Create self-signed certificate
_tprintf(_T("CertCreateSelfSignCertificate... "));
pCertContext = CertCreateSelfSignCertificate(NULL, &SubjectIssuerBlob, 0, &KeyProvInfo, &SignatureAlgorithm, 0, &EndTime, 0);
if (!pCertContext)
{
// Error
_tprintf(_T("Error 0x%x\n"), GetLastError());
return 0;
}
else
{
_tprintf(_T("Success\n"));
}// Open Root cert store in machine profile
_tprintf(_T("CertOpenStore... "));
hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_SYSTEM_STORE_LOCAL_MACHINE, L"Root");
if (!hStore)
{
// Error
_tprintf(_T("Error 0x%x\n"), GetLastError());
return 0;
}
else
{
_tprintf(_T("Success\n"));
}// Add self-signed cert to the store
_tprintf(_T("CertAddCertificateContextToStore... "));
if (!CertAddCertificateContextToStore(hStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, 0))
{
// Error
_tprintf(_T("Error 0x%x\n"), GetLastError());
return 0;
}
else
{
_tprintf(_T("Success\n"));
}// Just for testing, verify that we can access self-signed cert's private key
DWORD dwKeySpec;
_tprintf(_T("CryptAcquireCertificatePrivateKey... "));
if (!CryptAcquireCertificatePrivateKey(pCertContext, 0, NULL, &hCryptProvOrNCryptKey, &dwKeySpec, &fCallerFreeProvOrNCryptKey))
{
// Error
_tprintf(_T("Error 0x%x\n"), GetLastError());
return 0;
}
else
{
_tprintf(_T("Success\n"));
}
}
__finally
{
// Clean upif (!pbEncoded) {
_tprintf(_T("free... "));
free(pbEncoded);
_tprintf(_T("Success\n"));
}if (hCryptProvOrNCryptKey)
{
_tprintf(_T("CryptReleaseContext... "));
CryptReleaseContext(hCryptProvOrNCryptKey, 0);
_tprintf(_T("Success\n"));
}if (pCertContext)
{
_tprintf(_T("CertFreeCertificateContext... "));
CertFreeCertificateContext(pCertContext);
_tprintf(_T("Success\n"));
}if (hStore)
{
_tprintf(_T("CertCloseStore... "));
CertCloseStore(hStore, 0);
_tprintf(_T("Success\n"));
}
}
}int _tmain(int argc, _TCHAR* argv[])
{
SelfSignedCertificateTest();_tprintf(_T("<< Press any key>>\n"));
_getch();
return 0;
}
I hope this helps.
Regards,
Alex (Alejandro Campos Magencio)
Comments: