Attack
防止對 AES 加密數據進行可預測的修改
我對密碼學相當陌生,正在嘗試找出這種情況的最佳實踐。假設我有一些程式碼將用於傳遞加密的電子郵件地址。我對其進行加密並在連結中傳遞編碼數據:
// pass in "bill@microsoft.com" public String encryptMessage(final String message) throws Exception { // cipher created with Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.get().init(Cipher.ENCRYPT_MODE, secretKey); byte[] cipherText = cipher.get().doFinal(message.getBytes()); AlgorithmParameters params = cipher.get().getParameters(); byte[] iv = params.getParameterSpec(IvParameterSpec.class).getIV(); byte[] data = Arrays.copyOf(iv, iv.length + cipherText.length); System.arraycopy(cipherText, 0, data, iv.length, cipherText.length); return Base64.encodeBase64URLSafeString(data); }
現在,接收者將生成的字元串傳回,但猜測前 16 個字節是 IV(這是隨機數嗎?)並對它們進行修改,從而在加密數據中創建(半)可預測的更改。例如,以下程式碼中對字節 5 的更改在大多數情況下會將“bill@microsoft.com”更改為“bill@oicrosoft.com”或“bill@kicrosoft.com”。(假設我想註冊這些域來攔截電子郵件):
public String decryptMessage(final String message) throws Exception { byte[] encData = Base64.decodeBase64(message); encData[5] += 2; // Attacker modifies IV to create a predictable change in the data cipher.get().init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(Arrays.copyOfRange(encData, 0, 16))); byte[] plaintext = cipher.get().doFinal(Arrays.copyOfRange(encData, 16, encData.length)); return new String(plaintext); }
我應該怎麼做才能防止這種情況發生 - 這是我應該使用某種數字簽名以確保攻擊者無法更改數據的情況,還是有更好的方法在這裡使用加密?