Reputation: 432
I am trying to sign a public/private key pair by a temporary Root CA, steps followed are next:
CertCreateSelfSignCertificate
) (Done)CryptGenKey
) (Done)CertCreateSelfSignCertificate
function, nevertheless it seems that it is not possible...)I have been following the steps mentioned in next link: link
With powershell works fine, but I don't know how to implement it with Microsoft CryptoApi C++. Example Powershell:
$testCert = New-SelfSignedCertificate -CertStoreLocation Cert:\LocalMachine\My -DnsName "SignedByRootCA" -KeyExportPolicy Exportable -KeyLength 2048 -KeyUsage DigitalSignature,KeyEncipherment -Signer $rootCert
Currently, I obtain a certificate without private key, so how can I assign a private key to my signed certificate? My current code is showed below:
// Open the CA cert to get the issuer information and a handle to sign the cert
PCCERT_CONTEXT caCert = NULL;
CertificateStore certStore{};
certStore.Open(certStore.ROOT);
certStore.FindCertContext(tmpThumbprint, caCert);
NCRYPT_KEY_HANDLE caKey = NULL;
DWORD caKeySpec = 0;
BOOL fCallerFreeProvOrNCryptKey = FALSE;
CryptAcquireCertificatePrivateKey(caCert, CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, NULL, &caKey, &caKeySpec, &fCallerFreeProvOrNCryptKey);
// A structure which contains the information of a certificate
CERT_INFO certificateInfo;
memset(&certificateInfo, 0, sizeof(CERT_INFO));
certificateInfo.dwVersion = CERT_V3;
certificateInfo.SignatureAlgorithm = signatureAlgorithm;
certificateInfo.NotBefore = notBefore;
certificateInfo.NotAfter = notAfter;
certificateInfo.Issuer = caCert->pCertInfo->Subject;
certificateInfo.Subject = static_cast<CERT_NAME_BLOB>(*subject);
certificateInfo.cExtension = 1;
certificateInfo.rgExtension = certExt;
BYTE serialNumber[16];
CryptGenRandom(caKey, 16, serialNumber);
certificateInfo.SerialNumber.pbData = serialNumber;
certificateInfo.SerialNumber.cbData = 16;
// Exports the public key information associated with the corresponding private key of the provider.
bool result = false;
PCERT_PUBLIC_KEY_INFO pkInfo = NULL;
CryptExportPublicKeyInfo(csp.Get(), AT_KEYEXCHANGE, X509_ASN_ENCODING, NULL, &cbEncode);
pkInfo = (PCERT_PUBLIC_KEY_INFO)malloc(cbEncode);
CryptExportPublicKeyInfo(csp.Get(), AT_KEYEXCHANGE, X509_ASN_ENCODING, pkInfo, &cbEncode);
certificateInfo.SubjectPublicKeyInfo = *pkInfo;
// Encode and sign Certificate and decode
result = CryptSignAndEncodeCertificate(caKey, caKeySpec, X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, &certificateInfo, &signatureAlgorithm, NULL, nullptr, &cbEncode);
pbEncode = (BYTE*)malloc(cbEncode);
result = CryptSignAndEncodeCertificate(caKey, caKeySpec, X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED, &certificateInfo, &signatureAlgorithm, NULL, pbEncode, &cbEncode);
PCCERT_CONTEXT certContext = CertCreateCertificateContext(X509_ASN_ENCODING, pbEncode, cbEncode);
result = CryptAcquireCertificatePrivateKey(certContext, CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG, NULL, &caKey, &caKeySpec, &fCallerFreeProvOrNCryptKey); //FAILS!!! Error NTE_BAD_PUBLIC_KEY
DWORD e = GetLastError();
Are there any way to do it?
Upvotes: 5
Views: 1101