2017-06-01 83 views
0

我在this question中閱讀了關於從本機組件導入公鑰的內容。 我試着對基於BLOB文檔的私鑰執行相同的操作,但是我收到NTE_BAD_DATA錯誤。C++從xml導入CAPI/CNG中的RSA私鑰

我的想法是否可行?如果是這樣,你能幫忙嗎?

我嘗試:

void old_RSA_decrypt(PBYTE blob, DWORD blobSize) 
{ 
    HCRYPTPROV hCryptProv = NULL; 
    HCRYPTKEY hKey = NULL; 
    DWORD dwDecryptedLen = 0; 
    DWORD length; 
    std::ifstream f; 
    f.open("c:\\Programming\\encrypted.txt", std::ios::binary); 
    if (!f.is_open()) 
    { 
     std::cout << "Error on open file: " << GetLastError() << std::endl; 
     return; 
    } 

    f.seekg(0, f.end); 
    length = f.tellg(); 
    f.seekg(0, f.beg); 

    char * buffer = new char[length]; 
    f.read(buffer, length); 

    if (!f) 
     std::cout << "error: only " << f.gcount() << " could be read" << std::endl; 
    f.close(); 

    PBYTE bBuffer = (PBYTE)buffer; 

    //now to get the decryption thing going 

    if (!CryptAcquireContext(
     &hCryptProv, 
     NULL, 
     MS_STRONG_PROV, 
     PROV_RSA_FULL, 
     CRYPT_VERIFYCONTEXT)) 

    { 
     std::cout << "Error on CryptAcquireContext " << GetLastError() << std::endl; 
     return; 
    } 
    if (!CryptImportKey(
     hCryptProv, 
     blob, 
     blobSize, 
     NULL, 
     0, 
     &hKey)) 
    { 
     std::cout << "Error on CryptImportKey " << GetLastError() << std::endl; 
     return; 
    } 
    if (!CryptDecrypt(hKey, NULL, TRUE, 0, NULL, &dwDecryptedLen)) 
    { 
     std::cout << "Error on CryptDecrypt (First Pass) " << GetLastError() << std::endl; 
     return; 
    } 
    PBYTE decBuffer = new BYTE[dwDecryptedLen]; 
    for(int i = 0; i < length ; ++i) 
     decBuffer[i] = bBuffer[i]; 

    if (!CryptDecrypt(hKey, NULL, TRUE, 0, decBuffer, &length)) 
    { 
     std::cout << "Error on CryptDecrypt (Second Pass) " << GetLastError() << std::endl; 
     return; 
    } 
    std::cout << "Yurika2!" << std::endl; 
    std::ofstream of; 
    of.open("c:\\Programming\\decrypted.txt", std::ios::binary); 
    if (!of.is_open()) 
    { 
     std::cout << "Error on open write file: " << GetLastError() << std::endl; 
     return; 
    } 
    string sDecMsg = string(reinterpret_cast<char*>(decBuffer), length); 
    of << sDecMsg << std::endl; 
    of.close(); 
cleanup: 
    delete[] buffer; 
    delete[] decBuffer; 

} 

void do_decrypt() 
{ 
    string modStr = "yVUndgQFuB5Z5FgC0/WgWCg6Y8VuB582avGjQDdeoJDa1+RBKCyXo700sAMSGjM/bVakOlFqvCsVFNBysx1CH731CDb2DR1a0bsmYmDQ9d0ZHX+AOohVDIx9mc7bkDQZoEFpe9NqFsu95Y9yktpl1JKPmKyLOFgufGJYYvQyoOM="; 
    string expStr = "AQAB"; 
    string PStr = "/JydNn89lSWjgWOG1XRJm1qTWDekzzoLfTQU+GK+h8DGQ6gkUbgqGosLGo+eAxbO/ETZV3ibbBuIdvL4UxC5Qw=="; 
    string QStr = "zAh23Gc8Oqz/Uh2wh+yt8DqUesVLwMn2koc9CbyF9/Z5Qe8OIR4yygJtuYruRC1x/KYj85l6DGzstUZOtYmv4Q=="; 
    string DPStr ="+1INj1SUPjjOLUKJuQAS4z7/7PqfO5RyLcSNQHltOb5vAozcZXkmWnYPPAO6nzQoBg+xdDcH2kyiPkWJDYtL5Q=="; 
    string DQStr = "cbYh8HJEufrijTRox0hcJG+xgr7kmjy1BDMFDKEaFPkz2VBPEpwO+FDkMC1C35JoXcOGc+RMhhJK1jip8zkaYQ=="; 
    string InverseQStr = "3PAXzlAXgvLVrbOEygjA2zhJEYALBEi6VTKqfDKlnv8/D9QUkC39bEDIRLG0wMFFxN8NlLx5zTiiVswxnMy8Mw=="; 
    string DStr = "KKBSyKkyID+bowyxcWUAuJlRgv19YPNbL0RYTWZ+5UalqmfoT/uDk+pjndrYxcmulFkl5ZC1SYgmBl+zrXoLc/Ei86BtNiuwfcqHlUDp0fdP+fyYN45wh/251HQ3UM1zBpMP8XeYB6zjpCU/s3/wCBE6WpJWN9fKcG0W5PLq8eE="; 

    //FROM STRINGS TO BYTE VECTORS! 
    vector<BYTE> modBinMSB = base64_decode(modStr); 
    vector<BYTE> expBinMSB = base64_decode(expStr); 
    vector<BYTE> PBinMSB = base64_decode(PStr); 
    vector<BYTE> QBinMSB = base64_decode(QStr); 
    vector<BYTE> DPBinMSB = base64_decode(DPStr); 
    vector<BYTE> DQBinMSB = base64_decode(DQStr); 
    vector<BYTE> InverseQBinMSB = base64_decode(InverseQStr); 
    vector<BYTE> DBinMSB = base64_decode(DStr); 

    //TURN MSB TO LSB 

    DWORD offset = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY); // to keep track of things 
    const DWORD modulusLengthInBytes = 128; 
    DWORD keyBlobLength = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + (modulusLengthInBytes * 4) + (modulusLengthInBytes/2); 
    BYTE* keyBlob = (PBYTE)malloc(keyBlobLength); 
    BLOBHEADER* blobheader = (BLOBHEADER*)keyBlob; 
    blobheader->bType = PRIVATEKEYBLOB; 
    blobheader->bVersion = CUR_BLOB_VERSION; 
    blobheader->reserved = 0; 
    blobheader->aiKeyAlg = CALG_RSA_KEYX; 
    RSAPUBKEY* rsapubkey = (RSAPUBKEY*)(keyBlob + sizeof(BLOBHEADER)); 
    rsapubkey->magic = 0x31415352; 
    rsapubkey->bitlen = modulusLengthInBytes * 8 *4 + modulusLengthInBytes*4; 
    rsapubkey->pubexp = MSBByteVectorToDword(expBinMSB); 

    BYTE* modulus = keyBlob + offset; 
    copyReversed(modBinMSB, modulus); 
    offset += modulusLengthInBytes; 
    BYTE* prime1 = keyBlob + offset ; 
    copyReversed(PBinMSB, prime1); 
    offset += modulusLengthInBytes/2; 
    BYTE* prime2 = keyBlob + offset; 
    copyReversed(QBinMSB, prime2); 
    offset += (modulusLengthInBytes/2); 
    BYTE* exponent1 = keyBlob + offset; 
    copyReversed(DPBinMSB, exponent1); 
    offset += (modulusLengthInBytes/2); 
    BYTE* exponent2 = keyBlob + offset; 
    copyReversed(DQBinMSB, exponent2); 
    offset += (modulusLengthInBytes/2); 
    BYTE* coefficient = keyBlob + offset; 
    copyReversed(InverseQBinMSB, coefficient); 
    offset += modulusLengthInBytes/2; 
    BYTE* privateExponent = keyBlob + offset; 
    copyReversed(DBinMSB, privateExponent); 

    old_RSA_decrypt(keyBlob, keyBlobLength); 
} 

回答

0

這當然可以這樣做。你剛纔提到了Windows密碼棧,並且有一定的差異:

  • 編碼:
    • CAPI:所有的可變長度字段是小端。
    • CNG:所有可變長度字段都是big-endian。
  • 剛性:
    • CAPI:模量和d必須具有相同的長度。另外,P,Q,DP,DQ,InverseQ都具有相同的長度(它必須是模數長度的一半)。
    • CNG:私鑰只詢問n,e,p和q ...並且您分別指定每個字段的長度。

我看到你的代碼,一個明顯的錯誤:

rsapubkey->bitlen = modulusLengthInBytes * 8 *4 + modulusLengthInBytes*4; 

the documentation

bitlen

在模數的位數。在實踐中,這必須始終是八的倍數。

所以才

rsapubkey->bitlen = modulusLengthInBytes * 8; 

你的dwMagic值的設置似乎是不正確的,太。

rsapubkey->magic = 0x31415352; 

0x31415352是RSA_PUB_MAGIC,所以你稱自己爲公鑰。你想要RSA_PRIV_MAGIC(並使用常量)。

rsapubkey->magic = RSA_PRIV_MAGIC; 

比較來http://source.dot.net/#System.Security.Cryptography.Csp/System/Security/Cryptography/CapiHelper.Shared.cs,b7bc764e6deb34f5,這是在C#中的工作BLOB作家。

+0

試過了你的建議,沒有明顯的效果。任何其他想法? –

+0

您對'magic'的價值似乎也是可疑的。更新了答案,幷包含了一個指向.NET blob編寫器的鏈接。 – bartonjs

+0

這樣做,謝謝。爲了將來的參考,魔術應該是0x32415352,如此處所述:https://msdn.microsoft.com/en-us/library/windows/desktop/aa375601(v=vs.85).aspx#priv_BLOB –