私はAES/GCM/NoPadding
Javaで暗号化を使用しています(私はそれにかなり慣れていません)。私が正しく理解している場合、GCMは暗号化されたメッセージが操作されたかどうかを認識し、そうであれば復号化すべきではありません。このアンサーに記載されているように:
認証 TAG は復号化への入力です。誰かが関連付けられたデータまたは暗号化されたデータを改ざんした場合、GCM 復号化はこれに気づき、データを出力しません (またはエラーを返し、受信したデータを処理せずに破棄する必要があります)。
ただし、私のコードでは、暗号化されたメッセージ (メッセージ部分またはタグ部分) を変更すると、エラーは発生せず、メッセージは復号化されます (もちろん異なります)。メッセージは正しく復号化されませんが、別のキーを提供してもエラーは発生しません...
私は何を間違っていますか?以下のコードを参照してください。
ユーティリティ クラス:
public class CryptoUtils {
public static byte[] encrypt(byte[] key, byte[] iv, byte[] input) throws GeneralSecurityException {
try {
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivspec);
int outputLength = cipher.getOutputSize(input.length);
byte[] output = new byte[outputLength];
int outputOffset = cipher.update(input, 0, input.length, output, 0);
cipher.doFinal(output, outputOffset);
return output;
} catch (NoSuchAlgorithmException e) {
Timber.wtf(e);
}
return null;
}
public static byte[] decrypt(byte[] key, byte[] iv, byte[] encrypted) throws GeneralSecurityException {
try {
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivspec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivspec);
return cipher.doFinal(encrypted);
} catch (NoSuchAlgorithmException e) {
Timber.wtf(e);
}
return null;
}
}
エラーをスローしないコード:
byte[] key = getKey();
byte[] iv = generateIv();
byte[] message = "hello".getBytes();
byte[] encrypted = CryptoUtils.encrypt(key, iv, message);
//Split decrypted message into parts.
byte[] encryptedMessage = new byte[message.length];
System.arraycopy(encrypted, 0, encryptedMessage, 0, message.length);
byte[] tag = new byte[encrypted.length - message.length];
System.arraycopy(encrypted, message.length, tag, 0, tag.length);
//I am modifying the message here.
encryptedMessage[0] = 0;
// I am also modifying the key.
key[2] = 0;
//Put message and tag together.
byte[] toDecrypt = new byte[encrypted.length];
System.arraycopy(encryptedMessage, 0, toDecrypt, 0, encryptedMessage.length);
System.arraycopy(tag, 0, toDecrypt, encryptedMessage.length, tag.length);
//Still not getting any errors here.
byte[] decrypted = CryptoUtils.decrypt(key, iv, encryptedMessage);
byte[] decryptedMessage = new byte[message.length];
System.arraycopy(decrypted, 0, decryptedMessage, 0, message.length);
//Decrypted message is different than original.
Timber.d("Decrypted message: %s", new String(decryptedMessage));