0

我通过 java 实现这个,BouncyCastle Provider 使用 Block mode = ECB 和 Padding mode = PKCS7Padding

我noticte,如果我加密具有32字节的长度(例如61626162616261626162616261626162是abababababababab的十六进制值)i的数据得到的64字节长度的密码文本(f21ee0564ebd5274e10bf4590594b1e16a19592b917b19ee106f71d41d165289)是该密文是否有效?从我读到的内容来看,如果您加密小于 32 字节长度的数据,算法会将其填充为 32 字节长度并生成 32 字节长度的密文,但如果您输入的数据恰好为 32 字节长度,您不应该收到 32字节长度密文,如果我输入长度超过 32 字节的数据,它将正确填充到 64 字节密文

这就是我的代码的样子:

    public static byte[] encrypt(byte[] plainText, byte[] keyBytes)
        throws GeneralSecurityException {

    SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");

    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
    cipher.init(Cipher.ENCRYPT_MODE, key);

    byte[] cipherText = cipher.doFinal(plainText);

    return cipherText;
}

谢谢你的回复

4

2 回答 2

3

您混淆了十六进制字符和字节。两个十六进制字符可以用来表示一个字节。所以你的输入可能是 16 个字节,然后你的输出变成 32 个字节。AES 是 128 位 = 16 字节的分组密码。

PKCS#7 填充被定义为填充 16 字节块密码。为了确保纯文本的最后一个字节不会被误认为是填充,PKCS#7 填充总是填充。这意味着在纯文本可被 16 整除的不幸情况下,它将添加整个填充块。填充由一串字节组成,指示每个字节中字符串的长度,因此对于您的情况,填充由以下字节组成,用十六进制表示:10101010101010101010101010101010

请注意,Java 的默认提供程序使用"PKCS5Padding"而不是"PKCS7Padding". 两者是相同的,尽管 PKCS#5 填充正式仅适用于 64 位 = 8 字节的分组密码。Bouncy Castle 也将接受该字符串,因此"PKCS5Padding"为了兼容性,最好指定。

没有为 AES 指定使用 32 字节的填充,因为它只是一个 16 字节的分组密码。Rijndael-256 是一种 32 字节的分组密码,但该算法尚未被 NIST 标准化,因此应避免使用。

于 2012-11-06T14:55:27.757 回答
1

PKCS7 填充在这里解释: http ://en.wikipedia.org/wiki/Padding_(cryptography)#Byte_padding

它添加了之间1blockLength字节,所有这些都等于填充的大小。这意味着您的消息将被 16 个 16 填充,创建一个 32 字节的消息,随后使用 AES 进行编码。

请注意,您的消息是 16 个字节,而不是 32 个字节。

一般来说,从不使用零长度的填充,因为它无法与非零填充区分开来(并且填充必须以可逆的方式完成)。

于 2012-11-06T10:27:52.140 回答