【问题标题】:Java AES encryption weird resultJava AES加密奇怪的结果
【发布时间】:2012-08-31 11:18:28
【问题描述】:

我正在尝试使用 AES 算法加密一个简单的字符串。 一切似乎都很好,我能够解密它。 只是出于好奇,我将加密的数据打印到控制台,然后我 看到它很惊讶。

输入字符串:原始文本字符串。

加密数据:Díå¼[¶cE¶Ÿ¸'E,;èýaó1ÒŽ&ýÈZ

解密数据:原始文本字符串。

谁能解释一下为什么加密的数据位是输入字符串的两倍长..?

【问题讨论】:

    标签: encryption aes


    【解决方案1】:

    加密适用于固定大小的数据块。在编码过程中添加适当的填充,在解码过程中删除。

    【讨论】:

    • 感谢您的回复,约翰。所以这意味着在这种情况下剩余的(128 - 16)位正在被填充? (因为 AES 适用于 128 位块大小)
    • 大多数(全部?)加密算法使用块大小 == 密钥大小。所以 128 位密钥的 AES 使用 128 位块。
    • 是的,但我想知道的是剩余的位是否被填充。如果是,那么是什么?我可以明确地填充剩余的位吗?
    • 确实如此。而且您不想控制该填充。出于安全原因,它是按照特定算法完成的。作为一个退化的例子,假设你加密了一个字节并用零填充。知道这一点并阅读您的加密密文的攻击者可以将其用作“预言机”。攻击者猜测你的密钥并通过加密所有 256 个可能的明文值来确认它,然后将加密的密文与你的进行比较。
    • 您混淆了位和字节。您正在加密一个 16 个字符的字符串,该字符串在编码为字节时可能变成 16 个字节加上一个空终止符。所以 17 字节 * 每个字节 8 位 = 136 位要加密。这意味着两个 128 位块。
    【解决方案2】:

    我不会依赖显示一个特殊的字符串来判断它的长度。在加密时,您通常会得到一个byte[]length 应该为您提供确切的值。如果要打印,十六进制表示看起来更清晰:

    public static void showHex(byte[] data) {
        final String HEXDIGITS = "0123456789abcdef";
        StringBuilder res = new StringBuilder();
    
        for (int i = 0; i < data.length; i++) {
            int v = data[i] & 0xff;
            res.append(HEXDIGITS.charAt(v >> 4));
            res.append(HEXDIGITS.charAt(v & 0xf));
        }
    
        System.out.println(res);
    }
    

    【讨论】:

    • 感谢 f_puras 的回复。我尝试了您的代码并得出了不同的结果。当我使用 aes 加密 16 位长度的字符串时,我得到 32 位长度的加密数据,如果我加密 15 位长度的字符串,我得到 16 位长度的加密数据..你能解释一下为什么会这样吗?
    • 正如@johnwatts 已经提到的,您必须考虑填充。
    • Puru,填充总是发生,所以一个 16 字节的纯文本会得到一个完整的填充块。这允许 unpadding 机制工作,而不管明文结尾的值是多少; unpadding 机制可以通过这种方式区分填充和纯文本。
    猜你喜欢
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    • 2012-06-06
    • 1970-01-01
    • 1970-01-01
    • 2012-05-11
    • 1970-01-01
    相关资源
    最近更新 更多