2015-06-08 8 views
10

विंडोज सीएनजी एपीआई का उपयोग करके, मैं जीसीएम मोड में एईएस का उपयोग करके प्रमाणीकरण के साथ डेटा के व्यक्तिगत ब्लॉक को एन्क्रिप्ट और डिक्रिप्ट करने में सक्षम हूं। अब मैं एक पंक्ति में कई बफर एन्क्रिप्ट और डिक्रिप्ट करना चाहता हूं।जीसीएम मोड में एईएस का उपयोग करके BCryptEncrypt और BCryptDecrypt को कैसे कॉल करें?

documentation for CNG के अनुसार, इस परिदृश्य पर समर्थित है:

एन्क्रिप्शन या डिक्रिप्शन के लिए इनपुट कई बफ़र्स में फैले है, तो आप चाहिए BCryptEncrypt और BCryptDecrypt कार्यों के लिए श्रृंखला कॉल। Dwflags सदस्य में BCRYPT_AUTH_MODE_IN_PROGRESS_FLAG ध्वज सेट करके चेनिंग इंगित की जाती है।

अगर मैं इसे सही ढंग से समझते हैं, इसका मतलब है कि मैं कई बफ़र्स पर BCryptEncrypt क्रमिक रूप से आह्वान ख़त्म होने वाला संयुक्त बफ़र्स के लिए प्रमाणीकरण टैग को प्राप्त कर सकते हैं। इसी प्रकार, मैं अंत तक वास्तविक प्रमाणीकरण जांच का निर्धारण करते समय अनुक्रमिक रूप से एकाधिक बफर पर BCryptDecrypt का आह्वान कर सकता हूं। मैं इसे काम करने के लिए नहीं मिल सकता है, ऐसा लगता है कि dwFlags के मान को अनदेखा किया गया है। जब भी मैं BCRYPT_AUTH_MODE_IN_PROGRESS_FLAG का उपयोग करता हूं, तो मुझे 0xc000a002 का वापसी मान मिलता है, जो के बराबर है जैसा कि ntstatus.h में परिभाषित किया गया है।

हालांकि पैरामीटर pbIV/बाहर में के रूप में चिह्नित किया जाता है, तत्वों पैरामीटर pbIVBCryptEncrypt() द्वारा संशोधित नहीं मिलता द्वारा की ओर इशारा किया। क्या यह उम्मीद है? मैंने BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO संरचना में pbNonce फ़ील्ड को भी देखा, pPaddingInfo पॉइंटर द्वारा इंगित किया गया, लेकिन वह भी संशोधित नहीं होता है। मैंने चतुर्थ योजना को "मैन्युअल रूप से" करने की भी कोशिश की, काउंटर योजना के अनुसार सामग्री को संशोधित करना, लेकिन इससे कोई मदद नहीं मिली।

BCryptEncrypt और/या BCryptDecrypt सफलतापूर्वक कार्य करने की सही प्रक्रिया क्या है?

उत्तर

6

मैं इसे काम करने में कामयाब रहा। ऐसा लगता है कि समस्या एमएसडीएन में है, इसे BCRYPT_AUTH_MODE_IN_PROGRESS_FLAG के बजाय BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG सेटिंग का उल्लेख करना चाहिए।

#include <windows.h> 
#include <assert.h> 
#include <vector> 
#include <Bcrypt.h> 
#pragma comment(lib, "bcrypt.lib") 

std::vector<BYTE> MakePatternBytes(size_t a_Length) 
{ 
    std::vector<BYTE> result(a_Length); 
    for (size_t i = 0; i < result.size(); i++) 
    { 
     result[i] = (BYTE)i; 
    } 

    return result; 
} 

std::vector<BYTE> MakeRandomBytes(size_t a_Length) 
{ 
    std::vector<BYTE> result(a_Length); 
    for (size_t i = 0; i < result.size(); i++) 
    { 
     result[i] = (BYTE)rand(); 
    } 

    return result; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    NTSTATUS bcryptResult = 0; 
    DWORD bytesDone = 0; 

    BCRYPT_ALG_HANDLE algHandle = 0; 
    bcryptResult = BCryptOpenAlgorithmProvider(&algHandle, BCRYPT_AES_ALGORITHM, 0, 0); 
    assert(BCRYPT_SUCCESS(bcryptResult) || !"BCryptOpenAlgorithmProvider"); 

    bcryptResult = BCryptSetProperty(algHandle, BCRYPT_CHAINING_MODE, (BYTE*)BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM), 0); 
    assert(BCRYPT_SUCCESS(bcryptResult) || !"BCryptSetProperty(BCRYPT_CHAINING_MODE)"); 

    BCRYPT_AUTH_TAG_LENGTHS_STRUCT authTagLengths; 
    bcryptResult = BCryptGetProperty(algHandle, BCRYPT_AUTH_TAG_LENGTH, (BYTE*)&authTagLengths, sizeof(authTagLengths), &bytesDone, 0); 
    assert(BCRYPT_SUCCESS(bcryptResult) || !"BCryptGetProperty(BCRYPT_AUTH_TAG_LENGTH)"); 

    DWORD blockLength = 0; 
    bcryptResult = BCryptGetProperty(algHandle, BCRYPT_BLOCK_LENGTH, (BYTE*)&blockLength, sizeof(blockLength), &bytesDone, 0); 
    assert(BCRYPT_SUCCESS(bcryptResult) || !"BCryptGetProperty(BCRYPT_BLOCK_LENGTH)"); 

    BCRYPT_KEY_HANDLE keyHandle = 0; 
    { 
     const std::vector<BYTE> key = MakeRandomBytes(blockLength); 
     bcryptResult = BCryptGenerateSymmetricKey(algHandle, &keyHandle, 0, 0, (PUCHAR)&key[0], key.size(), 0); 
     assert(BCRYPT_SUCCESS(bcryptResult) || !"BCryptGenerateSymmetricKey"); 
    } 

    const size_t GCM_NONCE_SIZE = 12; 
    const std::vector<BYTE> origNonce = MakeRandomBytes(GCM_NONCE_SIZE); 
    const std::vector<BYTE> origData = MakePatternBytes(256); 

    // Encrypt data as a whole 
    std::vector<BYTE> encrypted = origData; 
    std::vector<BYTE> authTag(authTagLengths.dwMinLength); 
    { 
     BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authInfo; 
     BCRYPT_INIT_AUTH_MODE_INFO(authInfo); 
     authInfo.pbNonce = (PUCHAR)&origNonce[0]; 
     authInfo.cbNonce = origNonce.size(); 
     authInfo.pbTag = &authTag[0]; 
     authInfo.cbTag = authTag.size(); 

     bcryptResult = BCryptEncrypt 
      (
      keyHandle, 
      &encrypted[0], encrypted.size(), 
      &authInfo, 
      0, 0, 
      &encrypted[0], encrypted.size(), 
      &bytesDone, 0 
      ); 

     assert(BCRYPT_SUCCESS(bcryptResult) || !"BCryptEncrypt"); 
     assert(bytesDone == encrypted.size()); 
    } 

    // Decrypt data in two parts 
    std::vector<BYTE> decrypted = encrypted; 
    { 
     DWORD partSize = decrypted.size()/2; 

     std::vector<BYTE> macContext(authTagLengths.dwMaxLength); 

     BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO authInfo; 
     BCRYPT_INIT_AUTH_MODE_INFO(authInfo); 
     authInfo.pbNonce = (PUCHAR)&origNonce[0]; 
     authInfo.cbNonce = origNonce.size(); 
     authInfo.pbTag = &authTag[0]; 
     authInfo.cbTag = authTag.size(); 
     authInfo.pbMacContext = &macContext[0]; 
     authInfo.cbMacContext = macContext.size(); 

     // IV value is ignored on first call to BCryptDecrypt. 
     // This buffer will be used to keep internal IV used for chaining. 
     std::vector<BYTE> contextIV(blockLength); 

     // First part 
     authInfo.dwFlags = BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG; 
     bcryptResult = BCryptDecrypt 
      (
      keyHandle, 
      &decrypted[0*partSize], partSize, 
      &authInfo, 
      &contextIV[0], contextIV.size(), 
      &decrypted[0*partSize], partSize, 
      &bytesDone, 0 
      ); 

     assert(BCRYPT_SUCCESS(bcryptResult) || !"BCryptDecrypt"); 
     assert(bytesDone == partSize); 

     // Second part 
     authInfo.dwFlags &= ~BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG; 
     bcryptResult = BCryptDecrypt 
      (
      keyHandle, 
      &decrypted[1*partSize], partSize, 
      &authInfo, 
      &contextIV[0], contextIV.size(), 
      &decrypted[1*partSize], partSize, 
      &bytesDone, 0 
      ); 

     assert(BCRYPT_SUCCESS(bcryptResult) || !"BCryptDecrypt"); 
     assert(bytesDone == partSize); 
    } 

    // Check decryption 
    assert(decrypted == origData); 

    // Cleanup 
    BCryptDestroyKey(keyHandle); 
    BCryptCloseAlgorithmProvider(algHandle, 0); 

    return 0; 
} 
+0

सुझाव के लिए धन्यवाद, यह समझ में आता है। हालांकि यह काम नहीं कर रहा है, मैंने अपने प्रश्न के बारे में कुछ अतिरिक्त पाठ जोड़ा। –

+0

मैंने अपना जवाब पूरी तरह बदल दिया है। – Codeguard

+0

शानदार, बहुत धन्यवाद। एक टिप्पणी: 'trashIV' वास्तव में उन्नत चतुर्थ धारण करता है इसलिए चेनिंग मोड में उचित कार्य करने के लिए आवश्यक है। मेरी गलती यह थी कि मैंने IV को समान आकार के रूप में बनाया था ('गलत' 'dwFlags' मान का उपयोग करने के अलावा)। –

संबंधित मुद्दे