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/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 PROFILE

HCRYPTPROV 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 up

if (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 up

if (!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)


Share this article:

Comments:

Comments are closed.