Encryption

AES.decrypt(ct, wrong_key) 應該返回空白還是錯誤的結果?

  • January 15, 2019

我正在嘗試使用 AES 作為我正在建構的應用程序的密碼。我正在使用 JavaScript 庫 ( https://code.google.com/p/crypto-js/ ) 使用 AES 執行加密和解密。當我執行解密時,會發生這種情況:

AES.decrypt(ct, right_key) == 'message decrypted !' //true

AES.decrypt(ct, wrong_key) == '' //true

問題是我在一個過程中使用這個解密,在這個過程中不應該有任何方法來確定密鑰是對還是錯。我希望發生這樣的事情:

log(AES.decrypt(msg, wrong_key)) // 'random string fsdijw'

因此結果“符合”預期結果但不是預期結果,並且無法根據解密結果了解密鑰是對還是錯。我問了我的教授,他告訴我 AES 可能在那個庫中實施不好,但他並沒有那麼清楚地理解我的問題。

我想知道第一個程式碼片段中描述的行為是否是預期的,或者實際上 AES 在該庫中實現得不好。如果是預期的,是否有任何其他密碼算法不允許從解密結果中了解密鑰是對還是錯?

AES 是一種分組密碼,當使用錯誤的密鑰時會返回錯誤的數據。它僅適用於單個數據塊(16 個字節)。預設的 CBC 操作模式使您能夠加密多個數據塊。然後,填充使您能夠加密任意長度的明文。解密後必須以某種方式刪除填充。

您看到的是空白輸出,因為您的數據很短,並且填充刪除了不必要的字節。以下是CryptoJS中預設 PKCS#7 填充的實現方式:

unpad: function (data) {
   // Get number of padding bytes from last byte
   var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff;

   // Remove padding
   data.sigBytes -= nPaddingBytes;
}

因此,它查看解密字節的最後一個字節,並從密文中刪除盡可能多的字節。如果data.sigBytes是負數,它會像解密的 0 字節一樣處理它。如果您的消息長度超過 255 個字節,那麼解密肯定會列印一些東西,但它不會像初始明文一樣長。如果你總是想列印一些東西,那麼你需要在沒有填充的情況下解密。

我不會將此實現稱為錯誤,因為 PKCS#7 填充被指定為最多 256 個填充字節,但data.sigBytes -= Math.min(nPaddingBytes, blocksize);可能會更好。

零填充可能更適合您的情況,因為使用錯誤密鑰的解密不太可能導致明文以必須刪除的許多零字節結尾。但是,當您有可能加密以 0x00 字節結尾的明文時,不應使用諸如填充之類的方法。


因此結果“符合”預期結果但不是預期結果,並且無法根據解密結果了解密鑰是對還是錯。

這對於分組密碼通常是不可能的。使用錯誤的密鑰解密可能會導致一些任意純文字字節,這些字節不必組成具有有效 ASCII 或 UTF-8 編碼的字元串,如果你試圖強制它,你會得到錯誤,這可以用來區分正確的鑰匙來自錯誤的鑰匙。

如果您總是將明文編碼為十六進制,那麼您可以使用任意鍵。


有關的:

引用自:https://crypto.stackexchange.com/questions/32013