John Rainey
John Rainey

Reputation: 3

How do I use windows ncrypt API NCryptExportKey function, to get an unencrypted certificate key, in C/C++

I want to give access to a personnel certificate to another process, in PEM format. The process uses openssl.

I successfully export the cert to a blob...but something is wrong. NCRYPT_KEY_HANDLE hExportKey is set to NULL, so I assume the blob is not encrypted. Is this a good assumption? When I map the header of the blob to _BCRYPT_RSAKEY_BLOB* headerForRSA_blob, I get strange values. Why? -- "(_BCRYPT_RSAKEY_BLOB*) &pbOutput this is error. remove &" per comment –RbMm

The new _BCRYPT_RSAKEY_BLOB values are valid and updated in the code comments below. This implies the blob is good, but I'm not getting the BASE64 string I'm expecting???

//#define BCRYPT_RSAPUBLIC_MAGIC            0x31415352  // RSA1 826,364,754
//#define BCRYPT_RSAPRIVATE_MAGIC           0x32415352  // RSA2 843,141,970
//#define BCRYPT_RSAFULLPRIVATE_MAGIC       0x33415352  // RSA3 859,919,186

//              THIS WAS FIXED
//              AND CODE UPDATED
//*********************************************                                                 
//  headerForRSA_blob   0x0000007e66a7c498 {Magic=833680480 BitLength=634 cbPublicExp=3435973836 ...}   _BCRYPT_RSAKEY_BLOB *
//
//      Magic   833680480   unsigned long
//      BitLength   634 unsigned long
//      cbPublicExp 3435973836  unsigned long
//      cbModulus   3435973836  unsigned long
//      cbPrime1    3435973836  unsigned long
//      cbPrime2    3435973836  unsigned long
// *********************************************

// FIXED getting the structure
// _BCRYPT_RSAKEY_BLOB*) &pbOutput this is error.
// remove &" per comment –RbMm
        
//Magic     0x33415352  unsigned long   --  859919186 
//BitLength 0x00001000  unsigned long   --  4096
//cbModulus 0x00000200  unsigned long   --  512
//cbOutput  0x0000091b  unsigned long   --  2331
//cbPrime1  0x00000100  unsigned long   --  256
//cbPrime2  0x00000100  unsigned long   --  256     
        
debugPrintf("\n Obtained certificate NCRYPT_KEY_HANDLE\n");
NCRYPT_KEY_HANDLE hKey = phCryptProvOrNCryptKey;
NCRYPT_KEY_HANDLE hExportKey = NULL;
LPCWSTR pszBlobType = BCRYPT_RSAFULLPRIVATE_BLOB;
NCryptBufferDesc* pParameterList = NULL;
PBYTE pbOutput = NULL;
DWORD cbOutput = 0;
DWORD pcbResult = 0;
DWORD dwFlags = 0;
                                    
SECURITY_STATUS status = NCryptExportKey(
                            hKey,
                            hExportKey,
                            pszBlobType,
                            pParameterList,
                            pbOutput,
                            cbOutput,
                            &pcbResult,
                            dwFlags
                            );
                                    
    if (status != ERROR_SUCCESS)
    {
        this->MyHandleError("ERROR: NCryptExportKey FAILED\n");
    }
    else
    {
        if (pcbResult > 0)
        {
            if (pbOutput = (BYTE*)malloc(pcbResult))
            {
                cbOutput = pcbResult;
                SECURITY_STATUS status = NCryptExportKey(
                                                    hKey,
                                                    hExportKey,
                                                    pszBlobType,
                                                    pParameterList,
                                                    pbOutput,
                                                    cbOutput,
                                                    &pcbResult,
                                                    dwFlags
                                                );

                                                if (status != ERROR_SUCCESS)
                                                {
                                                    this->MyHandleError("ERROR: NCryptExportKey FAILED\n");                                                    
                                                }
                                                else
                                                {
                                                    LPSTR sz;
                                                    _BCRYPT_RSAKEY_BLOB*  headerForRSA_blob;
                                                    headerForRSA_blob =(_BCRYPT_RSAKEY_BLOB*) pbOutput;//per – RbMm comment changed &pbOutput to pbOutput

DWORD keySize = 0;
BOOL success = CryptBinaryToString(pbOutput,
              cbOutput,
              CRYPT_STRING_BASE64,
              NULL,
              &keySize);

if (success == FALSE)
{
    MyHandleError("get RSA private key FAILED CryptBinaryToString FAILED to get buffer size\n");  
}
else
{
    LPWSTR OutString = NULL;
    if (OutString = (LPWSTR)malloc((keySize + 1) * sizeof(TCHAR)))
    {
          debugPrintf("Memory for RSA private key has been allocated.\n");
          success = CryptBinaryToString(pbOutput,
                      cbOutput,
                      CRYPT_STRING_BASE64,
                      OutString,
                      &keySize);
      if (success == FALSE)
          {
              MyHandleError("get RSA private key FAILED CryptBinaryToString FAILED to get buffer\n");  
      }
      else
      {
        // got the key in BASE64
        ...
                                                    

Upvotes: 0

Views: 77

Answers (0)

Related Questions