2017-03-07 104 views
2

我需要在Java中解密AES加密字節。源數據以2個已知驗證字節開始,作爲成功解密的指示。由於某些協議原因,數據的長度小於255個字節,並且假如數據已經被加密的人需要填充數據,使用前面提到的相同驗證字節作爲填充。我用我的可用方法成功解密了數十萬條記錄。AES解密的有效結果在一個字節和一個字節上有多少可能不同?

現在我得到一些成功(?)解密後的一個和一個字節與解密結果不同的記錄。當然,這不是驗證字節;-),而是其他一個字節,具有非常特殊的記錄意義。總是有相同的字節,始終是相同的,不斷的錯誤值。我只是說,例如根據某些製造商的具體文檔,獲得0x47,我應該有0x44

就這麼簡單,根據我的文檔和結果,其他結果都是正確的。現在的問題是,我得到的數據製造商聲稱真的獲得0x44而不是我的0x47具有完全相同的輸入數據。不同我們有意見......

因爲我使用CipherAES/CBC/NoPadding和我的應用程序的調試解密我可以看到調用Cipher.final後,我已經在我的結果數據錯誤0x47。因爲我不覺得我的做法有任何錯誤,我決定測試替代AES解密器,發現3個不同的實現方式,聲稱我有完全一樣的輸入數據完全相同的結果(!):

有是其他AES解密器,但其中大多數不提供對init矢量的支持,因此不提供c直接結果。這就是整個觀點,不同的輸入會產生不同的輸出,根據我的測試,差異總是很大。從來不只是幾個字節發生了變化或者其他什麼,它總是完全錯誤的或者完全正確的,除了我看到的一個字節。

因此,如果實施了適當的AES,那麼對於相同的AES解密操作,同一個輸入是否會產生不同的結果?我不這麼認爲。

錯誤的輸入可能產生正確結果的可能性是多少,除了一個字節?因爲我的或其他輸入可能只是錯誤的,即使它被複制,我沒有看到任何區別。

錯誤的AES實現可能產生接近正確的結果的可能性有多大? Java有多大可能提供了錯誤的AES實現?我不這麼認爲。

關於我可以測試什麼的任何提示?對我來說,看起來我可能有3個不同的附加實現都證明了我的結果,所以我認爲我所做的是正確的,並且由於某些原因,一個特殊字節的差異需要來自其他地方。

謝謝!

回答

0

在這種情況下,看起來不正確的字節在第一個塊中,因此由不正確的IV引起。

擴展上的答案的評論:

的IV與數據的第一個塊異或,見CBC mode decryption。在加密時,IV的單字節(或比特)改變將影響所有字節,但是在解密時它僅影響第一塊中對應於IV中字節(或比特)不正確的字節(比特)。

另一種常見方法是將IV加入加密數據中,避免必須通過另一個通道/方法共享IV,以確保它是正確的。

這確實指出驗證方案很差。更好的方案考慮到所有加密字節,通常是加密數據的HMAC。但是在計算有限的環境中,CRC或甚至校驗和可能就足夠了。

1

除了一個字節,錯誤輸入是否可能產生正確結果的可能性有多大?

這可能是非常有可能的,這取決於輸入錯誤:我找到了差異,這是之一,這是不同的初始化向量只有一個字節和差異使得在實際的結果只有一個字節的差異。

初始化向量的區別來自對底層規範的不同理解,它定義瞭如何正確地構建init向量。數據來自某些需要在數據中包含版本號的設備,並且該規範允許同時在兩個不同的地方包含該版本。對於目前有問題的記錄,它有兩個不同的地方可用,但也有兩個不同的值。所以我從第一個地方使用版本號,而另一方使用第二個地方的版本號,並且由於兩個值不同,我們得到不同的初始化向量和不同的結果。

WTF ?! :-)

+1

IV與第一塊數據聯動,請參閱[CBC模式解密](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Cipher_Block_Chaining_.28CBC.29)。你不指定加密模式,我假設CBC模式。在加密時,單個字節會影響所有字節,但在解密時它只會影響IV中不正確的字節。 – zaph

0

在CBC模式下,使用密鑰對每個密文塊進行解密,然後將該結果與先前的密文塊進行XOR,以恢復純文本。

由於這是一個簡單的XOR操作,翻轉前面密文中的位將翻轉當前純文本塊中的相應位。 (當然,用翻轉的位對數據進行解密也會完全破壞前面的純文本塊)。

解密第一個塊時沒有「前一個」密文塊。這就是初始化向量進來的地方。它充當密碼文本的第零塊,並且如上所述,對IV的改變將導致第一個純文本塊中的比特改變。