2016-06-09 135 views
1

使用Microsoft CryptoAPI,我已經生成了一個新的RSA密鑰對,並且現在正試圖將私鑰導出到PKCS#8加密(受密碼保護)的PEM文件。如何使用MS CryptoAPI導出受密碼保護的私鑰?

我首先研究了CryptExportPKCS8()和CryptExportPKCS8Ex(),但前者不支持加密密鑰,後者是not exported by crypt32.dll。 MSDN說這兩個函數都被棄用了。

我現在的嘗試是通過從密碼到CryptExportKey(衍生)會話密鑰:()

HCRYPTPROV provider; 
BOOL result = CryptAcquireContext(&provider, CONTAINER_NAME, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_SILENT); 
HCRYPTKEY keyPair; 
result = CryptGenKey(provider, CALG_RSA_KEYX, (2048 << 16) | CRYPT_EXPORTABLE, &keyPair); 

HCRYPTHASH hash; 
result = CryptCreateHash(provider, CALG_SHA1, 0, 0, &hash); 
const char *password = "password"; 
result = CryptHashData(hash, (const BYTE *)password, strlen(password), 0); 
HCRYPTKEY sessionKey; 
result = CryptDeriveKey(provider, CALG_3DES, hash, CRYPT_EXPORTABLE, &sessionKey); 

DWORD blobSize; 
result = CryptExportKey(keyPair, sessionKey, PRIVATEKEYBLOB, 0, NULL, &blobSize); 
BYTE *blobBytes = new BYTE[blobSize]; 
result = CryptExportKey(keyPair, sessionKey, PRIVATEKEYBLOB, 0, blobBytes, &blobSize); 

DWORD derSize; 
// This throws "First-chance exception ... Access violation reading ..." and returns FALSE 
result = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, blobBytes, 0, NULL, NULL, &derSize); 
// error is 3221225477 (0xC0000005) 
DWORD error = GetLastError(); 
BYTE *derBytes = new BYTE[derSize]; 
result = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, blobBytes, 0, NULL, derBytes, &derSize); 

// ... CryptBinaryToString() to convert to PEM 

// ... Write PEM to file 

所有呼叫成功,直到評論CryptEncodeObjectEx。

如果我沒有將會話密鑰傳遞給CryptExportKey(),那麼我可以成功地使用CryptEncodeObjectEx()來對私鑰進行編碼,但顯然它是純文本的。

如何導出受密碼保護的私鑰?我推導會話密鑰的方式有什麼問題嗎? PKCS_RSA_PRIVATE_KEY是錯誤的編碼類型嗎?

我已經在Visual Studio 2013在Windows 7

回答

0

PKCS_RSA_PRIVATE_KEY測試時才使用未加密的私人密鑰團。當它加密時,您必須使用PKCS_ENCRYPTED_PRIVATE_KEY_INFO。工作代碼示例

BOOL expKey(PCSTR password) 
{ 
    BOOL fOk = FALSE; 
    HCRYPTPROV hProv; 
    if (CryptAcquireContext(&hProv, 0, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) 
    { 
     HCRYPTKEY hKey, hExpKey; 
     HCRYPTHASH hHash; 

     BOOL f = FALSE; 

     if (CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash)) 
     { 
      if (CryptHashData(hHash, (PBYTE)password, (ULONG)strlen(password), 0)) 
      { 
       f = CryptDeriveKey(hProv, CALG_3DES, hHash, 0, &hExpKey); 
      } 
      CryptDestroyHash(hHash); 
     } 

     if (f) 
     { 
      if (CryptGenKey(hProv, CALG_RSA_KEYX, RSA1024BIT_KEY*2|CRYPT_EXPORTABLE, &hKey)) 
      { 
       CRYPT_ENCRYPTED_PRIVATE_KEY_INFO cepki = {{ szOID_RSA_DES_EDE3_CBC}}; 
       if (
        CryptExportKey(hKey, hExpKey, PRIVATEKEYBLOB, 0, 0, &cepki.EncryptedPrivateKey.cbData) && 
        CryptExportKey(hKey, hExpKey, PRIVATEKEYBLOB, 0, cepki.EncryptedPrivateKey.pbData = (PBYTE)alloca(cepki.EncryptedPrivateKey.cbData), &cepki.EncryptedPrivateKey.cbData) 
        ) 
       { 
        ULONG cb; 
        PVOID pvEncoded; 
        if (CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_ENCRYPTED_PRIVATE_KEY_INFO, &cepki, CRYPT_ENCODE_ALLOC_FLAG, 0, &pvEncoded, &(cb = sizeof(PVOID)))) 
        { 
         fOk = TRUE; 
         LocalFree(pvEncoded); 
        } 
       } 
      } 
      CryptDestroyKey(hExpKey); 
     } 
     CryptReleaseContext(hProv, 0); 
    } 

    return fOk; 
} 
+0

pvEncoded是什麼格式? 'openssl asn1parse -inform DER -in test.der'顯示有效的ASN.1,但'openssl pkcs8 -inform DER -in test.der'給出'未知的pbe算法:evp_pbe.c:162:TYPE = des-ede3-cbc '。 –

相關問題