【问题标题】:Java How to check value is already AES encrypted;Java 如何检查值已经被 AES 加密;
【发布时间】:2018-06-13 10:53:53
【问题描述】:

我创建了一个工具来使用 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 加密字符串的字符串。这可能不太可能,但有可能。如果您无法明确定义输入应该是什么样子,我真的没有办法。
  • 我认为解决您的问题的更好方法是问自己为什么甚至存在双重加密的机会。如果您有一个充满加密值的表,为什么要对某些内容进行双重加密。如果有可能发生这种情况,请解决它,因为我很确定这更容易解决。
  • 呃,从外观上看,您使用的 IV 包含所有加密的全零。除非您为每次加密创建一个新密钥,否则您应该每次都生成一个新的 random IV。
  • 旁白:这个 "new String(cipherBytes, "UTF8")" 是有问题的。加密结果只是一个字节数组,不能假定该字节数组也总是代表字符串的有效 UTF8 编码。
  • 问题已经错了。 String 不是二进制数据的容器。你不应该有这个问题。您只需设计您的应用程序协议,使其不会出现。

标签: java encryption aes


【解决方案1】:

加密后,添加一些前缀,例如AES:。解密时,检查前缀是否存在(显然,删除它)。

许多密码实现都做类似的事情,前几个字节标识算法。

与任何好的加密方案一样,只有密钥必须是秘密的。该算法可以在不影响安全性的情况下公开。


唯一的边缘情况是真正的明文是否以前缀开头。如果您认为这值得考虑,那么您可以通过选择一个不太可能的前缀来降低风险(也许利用明文的知识)。为了进一步保证,您可以查看输入的长度,因为真实密文的长度保证是块大小的倍数。

【讨论】:

  • 如果表中的明文值以AES:开头怎么办?这个方案不可靠。
  • @JamesKPolk 没错,但没有更好的方法。前缀可以任意复杂,以将这种可能性降低到实际不可能的领域。为了进一步保证,您可以查看长度,因为真正密文的长度保证是块大小的倍数。
  • 这是正确的,但也许更好的方法是包含一个 MAC 值,比如 HMAC,或者只是使用像 AES-GCM 这样的模式。 MAC 值只会验证密钥是否正确以及数据是否未被损坏或篡改。第一个检查当然是字段的长度。前缀很常见,但它通常用作快速失败检查:如果前缀不匹配,那么我们知道这不是密码字段。之后通常会执行更稳健的检查。
【解决方案2】:

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

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

如果连续 10 个字节的 MSB 设置为零,则它成为密文的机会只有 2-10,即小于 0.1%。

但毕竟您将密文编码为十六进制字符串,因此您需要在分析期间将其反转。

如果您的明文恰好是压缩数据,那么机会就不是那么好,因为熵几乎与加密数据甚至随机数据一样高。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-20
    • 2011-06-05
    • 2018-01-09
    • 2012-03-28
    • 2012-06-01
    • 2017-05-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多