Как подписать с закрытым ключом RSA CNG - PullRequest
2 голосов
/ 26 февраля 2020

1. Как подписать с закрытым ключом RSA? ( решено )

Я следовал этому образцу , чтобы подписать данные закрытым ключом. Я только резервирую функции ha sh и подписываю их, и использую закрытый ключ ECDSA P-256, как в примере.

Вот мои шаги, и программа отлично работает:

  • BCryptOpenAlgorithmProvider()
  • Ха sh некоторые данные
  • NCryptOpenStorageProvider()
  • NCryptCreatePersistedKey()
  • NCryptFinalizeKey()
  • NCryptSignHash()
  • NCryptSignHash()

Я пытался подписать с закрытым ключом RSA, заменив NCRYPT_ECDSA_P256_ALGORITHM на NCRYPT_RSA_ALGORITHM и NCRYPT_RSA_SIGN_ALGORITHM, но через секунду NCryptSignHash() не удалось NTE_INVALID_PARAMETER.

    //create a persisted key
    if (FAILED(secStatus = NCryptCreatePersistedKey(
        hProv,
        &hKey,
        NCRYPT_RSA_ALGORITHM,
        L"my RSA key",
        0,
        0)))
    {
        wprintf(L"**** Error 0x%x returned by NCryptCreatePersistedKey\n", secStatus);
        goto Cleanup;
    }

2. Почему программа не может найти закрытый ключ после первого запуска?

Закрытый ключ создан в программе, я попытался подписать сертификат X509, который имеет закрытый ключ (ECDSA P-256) в My хранилище сертификатов.

Вот мои шаги и программа работает только при первом запуске. Не удалось в CryptAcquireCertificatePrivateKey() с NTE_BAD_KEYSET error

  • BCryptOpenAlgorithmProvider()
  • Ха sh некоторые данные
  • CertOpenStore()
  • CertFindCertificateInStore()
  • CryptAcquireCertificatePrivateKey()
  • NCryptSignHash()
  • NCryptSignHash()
   // Open the certificate store.
   if (!(hCertStore = CertOpenStore(
       CERT_STORE_PROV_SYSTEM,
       0,
       NULL,
       CERT_SYSTEM_STORE_CURRENT_USER,
       CERT_STORE_NAME)))
   {
       MyHandleError(const_cast<LPTSTR>("The MY store could not be opened."));
   }
   swprintf(wMY_SIGNER_NAME, 100, L"%hs", MY_SIGNER_NAME);
   if (pSignerCert = CertFindCertificateInStore(
       hCertStore,
       MY_ENCODING_TYPE,
       0,
       CERT_FIND_SUBJECT_STR,
       wMY_SIGNER_NAME,
       NULL))
   {
       //_tprintf(TEXT("The signer's certificate was found.\n"));
   }
   else
   {
       MyHandleError(const_cast<LPTSTR>("Signer certificate not found."));
   }

   if (CryptAcquireCertificatePrivateKey(
       pSignerCert, 
       CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG, NULL, 
       &hKey,
       &dwKeySpec, 
       false))
   {
       printf("Get Priv OK\n");
   }
   else
   {
       if (GetLastError() == NTE_BAD_KEYSET)
           printf("NTE_BAD_KEYSET\n");
   }

ОБНОВЛЕНИЕ:

    if (FAILED(secStatus = NCryptSignHash(
        hKey,
        0,
        pbHash,
        cbHash,
        NULL,
        0,
        &cbSignature,
        0)))
    {
        wprintf(L"**** Error 0x%x returned by NCryptSignHash1\n", secStatus);
        goto Cleanup;
    }

    //allocate the signature buffer
    pbSignature = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbSignature);
    if (NULL == pbSignature)
    {
        wprintf(L"**** memory allocation failed\n");
        goto Cleanup;
    }

    if (FAILED(secStatus = NCryptSignHash(
        hKey,
        0,
        pbHash,
        cbHash,
        pbSignature,
        cbSignature,
        &cbSignature,
        0)))
    {
        wprintf(L"**** Error 0x%x returned by NCryptSignHash2\n", secStatus);
        goto Cleanup;
    }

ОБНОВЛЕНИЕ2:

Код работает после удаления NCryptDeleteKey(hKey, 0). Я думаю, что этот API удаляет мой ключ E C! Но я не знаю, почему ключ RSA не удаляется?

...