Microsoft CryptoApi - создайте новый сертификат, подписанный сертификатом root. - PullRequest
4 голосов
/ 14 января 2020

Я пытаюсь подписать пару открытый / закрытый ключ с помощью временного Root CA, следующие шаги:

  1. Создать самозаверяющий root сертификат полномочий (CertCreateSelfSignCertificate ) ( Готово )
  2. Создание пары открытый / секретный ключ (CryptGenKey) ( Выполнено )
  3. Подпись пары открытый / секретный ключ с помощью root сертификат полномочий ( TODO ) (я пытался использовать функцию CertCreateSelfSignCertificate, тем не менее кажется, что это невозможно ...)

Я следил за шаги, упомянутые в следующей ссылке: ссылка

С PowerShell хорошо работает, но я не знаю, как реализовать это с Microsoft CryptoApi C ++. Пример Powershell:

$testCert = New-SelfSignedCertificate -CertStoreLocation Cert:\LocalMachine\My -DnsName "SignedByRootCA" -KeyExportPolicy Exportable -KeyLength 2048 -KeyUsage DigitalSignature,KeyEncipherment -Signer $rootCert

В настоящее время я получаю сертификат без закрытого ключа , так как я могу назначить закрытый ключ для моего подписанного сертификата? Мой текущий код показан ниже:

// 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();

Есть ли способ сделать это?

...