2012-02-01 58 views
2

首先,如果我在這裏丟失了某些東西,我很抱歉。這是我第一次嘗試Windows CryptAPI,雖然我已經通過谷歌,MSDN,MSDN的例子等,我不明白爲什麼會出現這個問題。 我有下面的代碼,它應該複製在特定地址找到的操作碼(字節塊),加密它們,然後將它們寫回。這絕不是一個完整的代碼,它的錯誤檢查很少。我正在使用AES256。CryptEncrypt AES 256在加密最後一塊時失敗

bool CryptoClass::encrypt(DWORD address, DWORD len) 
{ 
    DWORD dwBlockLen = 0; 
    DWORD dwBufferLen = 0; 
    DWORD dwCount = 0; 
    PBYTE pbBuffer = NULL;  
    dwBlockLen = AES_BLOCK_SIZE - AES_BLOCK_SIZE % ENCRYPT_BLOCK_SIZE; 
    dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE; 
    if(pbBuffer = (BYTE *)malloc(dwBufferLen)) 
    { 
     bool EOB = FALSE; 
     while (dwCount <= len)) 
     { 
      memcpy((void*)pbBuffer,(void*)address,dwBlockLen);    
      if ((len - dwCount) < dwBlockLen) EOB = TRUE;    

      if(CryptEncrypt(hKey,NULL,EOB,0,pbBuffer,&dwBlockLen,dwBufferLen)) 
      { 
       memcpy((void*)address,(void*)pbBuffer,dwBlockLen); 
       address += dwBlockLen;        
       dwCount += dwBlockLen;        
      } 
      else 
      { 
       error = GetLastError(); 
       MessageBoxA(NULL,"problem","error",MB_OK); 
      } 
     } 
     free(pbBuffer); 
     return true; 
    } 
    else return false; 
} 

從我的理解AES可以加密的16個字節的塊,所以AES_BLOCK_SIZE被定義爲16. 也是我ENCRYPT_BLOCK_SIZE被設置爲8。我基本上覆制我上MSDN找到一個例子,在調整了AES256和用於內存而不是文件。 但是,在我的while循環中,無論何時它到達緩衝區的末尾,FINAL被設置爲TRUE,CryptEncrypt都會失敗。我嘗試了很多不同的方式來做到這一點,但總是失敗。 是否因爲最後的緩衝區小於16字節? 有些人可以幫忙,當談到加密時,我是一個總諾貝爾。 謝謝 編輯:GetLastError返回:0x000000ea

+0

這到底是什麼ENCRYPT_BLOCK_SIZE做塊?你有指向所用示例的指針嗎? – 2012-02-01 21:43:59

回答

4

您收到錯誤ERROR_MORE_DATA。其轉換爲:

如果分配給pbData的緩衝區不足以容納加密數據,則GetLastError返回ERROR_MORE_DATA並將所需的緩衝區大小(以字節爲單位)存儲在pdwDataLen指向的DWORD值中。

如果方法使用CBC加密(微軟在它的智慧,不指定其API的模式或填充算法),那麼下面的算法應該以計算緩衝區的輸出尺寸:

BUFFER_SIZE =(plain_size_bytes/AES_BLOCK_SIZE + 1)* AES_BLOCK_SIZE;

換句話說,如果plain_size_bytes是N * AES_BLOCK_SIZE,您仍然需要一個完整的填充塊。這是因爲您始終需要執行填充,否則,非填充算法無法區分純文本和填充字節。

當然,您也可以簡單地創建一個plain_size_bytes + AES_BLOCK_SIZE緩衝區,並使用pdwDataLen值來獲取實際長度。

編輯:如果您單獨加密每個明文塊,和密碼使用CBC或ECB與填充,則最後平原塊可能需要2全因上述

+0

謝謝,確實如此。我只是使用了更大的緩衝區和塊大小,並解決了它。顯然我也不得不: CryptSetKeyParam(hKey,KP_MODE,(BYTE *)&dwMode,NULL); 其中設置了ECB模式。謝謝你的解釋:) – 2012-02-01 23:21:52

+1

ECB模式加密在幾乎所有情況下都是不安全的。它可以使用與CBC相同的填充機制(大多數時候使用PKCS#7填充),所以答案對兩者都有效。使用CBC而不是ECB,並用隨機IV預先安裝你的密文(r)。 – 2012-02-01 23:35:21

+0

我已經放了3天,試圖弄清楚爲什麼密文在使用ECB時不會解密。切換到CBC它在第一次嘗試。我希望我早點讀過你的評論,會爲我省去麻煩... – 2012-02-09 00:50:52

1
while (address < (address + len)) 

我神祕的答案是「想想吧 - 你會不太去想它永遠的,但是......」

+0

是的,我只是意識到,太累了,不能發現這一點。謝謝 ! 但是這並不能解決爲什麼CryptEncrypt在最後一個塊失敗的問題。 – 2012-02-01 05:21:22

+1

它可能解釋了爲什麼CryptEncrypt在最後一個塊之後失敗,但是在編輯完問題後沒有更多。 – 2012-02-01 05:37:39

0
if ((len - dwCount) < dwBlockLen) EOB = TRUE; 

也許應該是這樣的

if ((len - dwCount) < dwBlockLen) 
{ 
    EOB = TRUE; 
    dwBlockLen = ENCRYPT_BLOCK_SIZE; 
}