如何检查值是否已经进行了AES加密的Java方法?

4
我已经创建了一个工具,使用AES加密技术对我的表格数据进行加密。 加密方法
public String encrypt(String plainText) throws Exception {

        byte[] cipherBytes = null;

        log.info("Started encryption...");

        System.out.println("value before encryption :" + plainText);

        log.info("value before encryption :" + plainText);

        if (plainText != null && !plainText.isEmpty()) {
            if (cipher != null && key != null) {
                byte[] ivByte = new byte[cipher.getBlockSize()];
                IvParameterSpec ivParamsSpec = new IvParameterSpec(ivByte);
                cipher.init(Cipher.ENCRYPT_MODE, key, ivParamsSpec);
                cipherBytes = cipher.doFinal(plainText.getBytes());
                log.info("Completed encryption.");
                log.info("Encrypted data : " + new String(cipherBytes, "UTF8"));
                System.out.println("value after encryption" + Hex.encodeHexString(cipherBytes));
                log.info("value after encryption" + Hex.encodeHexString(cipherBytes));
                return Hex.encodeHexString(cipherBytes);
            } else {
                log.info("Encryption failed, cipher, key is null.");
                throw new RuntimeException(
                        "Encryption failed, cipher, key  is null.");
            }

        }


        return plainText;


    }
  • 输入字符串: John Doee
  • 加密输出: 4aa2173cb653f89e109b23218ecaea7f

我希望避免对我的表数据进行双重加密。我想要检查现有记录是否已经加密。有没有办法检查这个?


我并不认为有这样的可能性。想象一下你的输入是一个看起来像AES加密字符串的字符串。虽然这种情况可能不太可能发生,但也有可能。如果你无法清晰地定义输入应该是什么样子的,我真的看不出有什么办法。 - Ben
1
我认为解决您的问题的更好方法是问问自己为什么会出现双重加密的机会。如果您有一个充满加密值的表,为什么会有东西被双重加密呢?如果存在这种可能性,那么应该解决这个问题,因为我相信这样更容易修复。 - Ben
1
嗯,看起来你在每次加密时都使用由全零组成的IV。除非你为每个加密创建一个新的密钥,否则应该每次生成一个新的 随机 IV。 - Michael
@Ben,想象一下这样的情况。在加密过程运行时,在加密完成之前会插入一个新记录。最终表格数据不一致,因为表格中有加密和解密的记录。我该如何加密那个单独被解密的记录?一种方法是解密所有记录或手动更新该单个记录。这就是为什么我要避免双重加密的原因。 - Niranga Sandaruwan
3
注意:这个"new String(cipherBytes, "UTF8")"是有问题的。加密结果仅是一个字节数组,不能假设这个字节数组总是能表示一个有效的UTF8编码字符串。 - Erwin Smout
3
这个问题本身就有问题。"String"不是二进制数据的容器。您不应该遇到这个问题。您只需要设计您的应用程序协议,使它不会出现这种情况。 - user207421
2个回答

14
加密后,添加一些前缀,例如AES:。解密时,检查前缀是否存在(并显然删除它)。 许多密码实现都做类似的事情,其中前几个字节标识算法。 与任何好的加密方案一样,只有密钥必须保密。算法可以公开,而不会影响安全性。 唯一的边界情况是真正的明文以前缀开头。如果您认为这值得考虑,则可以通过选择不太可能的前缀(也许利用对明文的了解)来降低风险。为了进一步保证可靠性,可以查看输入的长度,因为真正的密文长度保证是块大小的倍数。

2
如果表中的明文值以 AES: 开头,那会怎样?这种方案是不可靠的。 - President James K. Polk
@JamesKPolk 是的,但没有更好的方法。前缀可以任意复杂,以将其可能性降至实际不可能的范围。为了进一步保证,您可以查看长度,因为真正的密文长度保证是块大小的倍数。 - Michael
1
这是正确的,但也许更好的方法是包括像HMAC这样的MAC值,或者只使用像AES-GCM这样的模式。 MAC值仅验证密钥是否正确以及数据是否未被损坏或篡改。当然,第一个检查将是字段长度。前缀很常见,但通常用作快速失败检查:如果前缀不匹配,则我们知道这不是密码字段。之后通常会执行更强大的检查。 - President James K. Polk

2

我同意Michael的观点,最好在你的密文前加上一些标记。但如果你不能这样做,也有一种概率方法:

你无法以100%的确定性识别原始加密数据。但是根据你的明文,你可能能够确定它是否未加密。例如,ASCII文本可以通过MSB进行识别。由于密文应该与随机噪声无法区分,因此加密数据具有相同模式的可能性很小。

如果10个连续字节的MSB设置为零,则其为密文的几率仅为2-10,即不到0.1%。

但毕竟你将密文编码为十六进制字符串,所以在分析过程中需要将其反转。

如果你的明文恰好是压缩数据,则情况并不那么好,因为熵几乎与加密或随机数据一样高。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接