0

AES/GCM/NoPadding在java中使用加密(我对它很陌生)。如果我理解正确,GCM 应该识别加密的消息是否被操纵,如果是,它不应该解密它。如this anwser所述:

身份验证 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));
4

0 回答 0