AES解密不能超过16个字节

时间:2015-11-06 00:13:49

标签: java encryption cryptography

我在Java中使用AES加密/解密时遇到了一个非常奇怪的问题。如果我正在加密/解密一个小于16字节的字符串,则密码可以正常工作,但如果我提供大于16字节的密码,我会收到错误“给定最终块没有正确填充”。我构建了一些小代码作为示例:

package com.company;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class Main {

    public static void main(String[] args) {
        try {
            Cipher aesEncrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");
            Cipher aesDecrypt = Cipher.getInstance("AES/CBC/PKCS5Padding");

            SecretKeySpec key = new SecretKeySpec("ABCDEQWERTASDFGA".getBytes(), "AES");

            IvParameterSpec ivSpec = new IvParameterSpec(new byte[16]);

            aesDecrypt.init(Cipher.DECRYPT_MODE, key, ivSpec);
            aesEncrypt.init(Cipher.ENCRYPT_MODE, key, ivSpec);

            byte[] message = "Hello".getBytes();

            aesEncrypt.update(message);

            byte[] encrypted = aesEncrypt.doFinal();

            aesDecrypt.update(encrypted);

            byte[] decrypted = aesDecrypt.doFinal();

            System.out.println(new String(decrypted, "UTF-8"));
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }
}

当byte []消息为“Hello”时,加密/解密工作正常,但当我将其更改为“HelloMyBabyHelloMyDarling”时,它会抛出异常。有谁知道我在这里做错了什么?

1 个答案:

答案 0 :(得分:3)

Cipher#update(byte[])会返回您因某些原因未使用的byte[]。您只是丢弃除最后一个块之外的所有内容(Cipher#doFinal()在应用填充后返回最后一个加密块)。如果您的消息只包含一个块,则密文和解密的明文将完整。

由于您使用短信,因此您根本不需要使用Cipher#update。只需使用Cipher#doFinal(byte[])

byte[] message = "Hello".getBytes();
byte[] encrypted = aesEncrypt.doFinal(message);
byte[] decrypted = aesDecrypt.doFinal(encrypted);

如果您尝试加密较长的数据(可能不适合内存),那么您应该将Cipher#update结果写入OutputStream或使用不带update或{{的CipherOutputStream 1}}来电。