2017-04-27 1092 views
-1

我需要在使用WinCrypt的C/C++應用程序的AES-128下加密字符串。我寫了一個程序來加密一個16字節的AES字符串(128位)的16字節字符串,但它不像預期的那樣工作(並且MSDN示例沒有幫助) 。使用WinCrypt的AES-128加密

我的主要問題是與調用CryptEncrypt,我可能沒有明確如何使用參數:

  • * pbData
  • * pdwDataLen
  • dwBufLen

這裏我的代碼:

#include <windows.h> 
#include <stdio.h> 
#include <wincrypt.h> 
#define ENCRYPT_ALGORITHM CALG_AES_128 

int main() 
{ 

    HCRYPTPROV hCryptProv; 
    HCRYPTKEY hKey; 

//--------------------------------------------------------------- 
// Get the handle to the provider. 
if(CryptAcquireContext(
    &hCryptProv, 
    NULL, 
    NULL, //MS_ENH_RSA_AES_PROV 
    PROV_RSA_AES, 
    0)) 
{ 
    printf("A cryptographic provider has been acquired. \n"); 
} 
else 
{ 
    printf("Error during CryptAcquireContext!\n"); 
    exit(1); 
} 


//--------------------------------------------------------------- 
// Create a random session key. 

if(CryptGenKey(
      hCryptProv, 
      ENCRYPT_ALGORITHM, 
      CRYPT_EXPORTABLE, //KEYLENGTH | CRYPT_EXPORTABLE, 
      &hKey)) 
{ 
     printf("A session key has been created.\n"); 
} 
else 
{ 
      printf("Error during CryptGenKey.\n"); 
      exit(1); 
} 
} 

char text_test [] = "abcdabcdabcdabcd"; 
    DWORD text_len = strlen(text_test); 

    printf("PlainText: %s\n",text_test); 
    printf("Buf Len: %d\n",text_len); 

    if (!CryptEncrypt(hKey, 
        NULL, // hHash = no hash 
        1, // Final 
        0,  // dwFlags 
        &text_test, //*pbData 
        &text_len, //*pdwDataLen 
        32)) {  //dwBufLen 
    printf("Encryption failed\n"); 
    } 

    printf("CipherText: %s\n",text_test); 
    printf("Len: %d\n",text_len); 

    if (!CryptDecrypt(hKey, 
        NULL, // hHash = no hash 
        1, // Final 
        0,  // dwFlags 
        &text_test, 
        &text_len)) { 
    printf("Decryption failed\n"); 
    } 

    printf("PlainText: %s\n",text_test); 
    printf("Len: %d\n",text_len); 
. 
. 
. 
CryptDestroyKey(hKey) 
. 
. 
CryptReleaseContext(hCryptProv, 0) 
. 

在cmd的輸出是:

enter image description here

任何人都可以解釋我爲什麼解密的字符串較長,這是正確的使用CryptEncrypt的三個參數的?我將最後一個值設置爲32,因爲經過一些試驗和錯誤之後,這是唯一使這個工作成功的值。請幫助,並提前謝謝你!

+0

我其餘的解密字符串是填充 – zapredelom

+0

@zapredelom是的,我認爲它可以填充,但我不知道如何正確使用CryptEncrypt的參數。 –

回答

1

我是新來crytography過,但是從here這個代碼可能有您的解決方案:

// This acts as both the length of bytes to be encoded (on input) and the 
    // number of bytes used in the resulting encrypted data (on output). 
    DWORD length = kAesBytes128; 
    if (!CryptEncrypt(hKey, 
        NULL, // hHash = no hash 
        true, // Final 
        0,  // dwFlags 
        reinterpret_cast<BYTE*>(encrypted->data()), 
        &length, 
        encrypted->length())) { 
    throw std::runtime_error("Encryption failed"); 
    } 

    // See comment above. 
    encrypted->chop(length - kAesBytes128); 

,否則我就會使用加密+

+0

謝謝,但在發佈我的問題之前我看到了這篇文章。在這個例子中,我不明白參數* pbData和dwBufLen。我不知道如何在我的代碼中使用它們。 –

+0

https://msdn.microsoft.com/en-us/library/windows/desktop/aa379924(v=vs.85).aspx是API文檔 'pbData - 指向包含明文的緩衝區的指針被加密。這個緩衝區中的明文用這個函數創建的密文覆蓋。' 'dwBufLen - 指定輸入pbData緩衝區的總大小(以字節爲單位)。' 對我來說似乎很簡單。 – PatrickB

+0

此外,AES是一個塊密碼,所以這個限制適用:'當使用塊密碼時,這個數據長度必須是塊大小的倍數,除非這是要加密的數據的最後部分並且最終參數是TRUE .' – PatrickB

0

這是填充有從一個類似的項目代碼的一些工作。默認情況下,您將獲得與您加密的字節相同數量的填充。忽略最後的16個字節。前16個字節是你想要的。