AES错误:给定最终块未正确填充

时间:2013-03-25 19:16:58

标签: java cryptography aes

我需要有关此错误的帮助:给定最终块未正确填充。从标题中可以看出,我正在使用AES。

以下是错误的行代码:

 byte[] decrypted = cipher.doFinal(bytes);

以下是完整代码:

public class AESCrypt {
private final Cipher cipher;
private final SecretKeySpec key;
private String encryptedText, decryptedText;

public AESCrypt(String password) throws Exception {
    // hash password with SHA-256 and crop the output to 128-bit for key
    MessageDigest digest = MessageDigest.getInstance("SHA-256");
    digest.update(password.getBytes("UTF-8"));
    byte[] keyBytes = new byte[16];
    System.arraycopy(digest.digest(), 0, keyBytes, 0, keyBytes.length);

    cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    key = new SecretKeySpec(keyBytes, "AES");
}

public String encrypt(String plainText) throws Exception {
    byte[] iv = new byte[cipher.getBlockSize()];
    new SecureRandom().nextBytes(iv);
    AlgorithmParameterSpec spec = new IvParameterSpec(iv);
    cipher.init(Cipher.ENCRYPT_MODE, key, spec);
    byte[] encrypted = cipher.doFinal(plainText.getBytes());
    encryptedText = asHex(encrypted);
    return encryptedText;
}

public String decrypt(String cryptedText) throws Exception {
    byte[] iv = new byte[cipher.getBlockSize()];
    AlgorithmParameterSpec spec = new IvParameterSpec(iv);
    cipher.init(Cipher.DECRYPT_MODE, key, spec);
    // decrypt the message
    byte[] bytes = cryptedText.getBytes("UTF-8");
    byte[] decrypted = cipher.doFinal(bytes);
    decryptedText = asHex(decrypted);
    System.out.println("Desifrovani tekst: " + decryptedText + "\n");

    return decryptedText;
}

public static String asHex(byte buf[]) {
    StringBuilder strbuf = new StringBuilder(buf.length * 2);
    int i;
    for (i = 0; i < buf.length; i++) {
        if (((int) buf[i] & 0xff) < 0x10) {
            strbuf.append("0");
        }
        strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
    }
    return strbuf.toString();
}

public static void main(String[] args) throws Exception {

    System.out.print("....AES....\n");

    String message = "MESSAGE";
    String password = "PASSWORD";

    System.out.println("MSG:" + message);

    AESCrypt aes = new AESCrypt(password);
    String encryptedText = aes.encrypt(message).toString();
    System.out.println("SIFROVANA PORUKA: " + encryptedText);
    String decryptedText = aes.decrypt(encryptedText).toString();       
    System.out.print("DESIFROVANA PORUKA: " + decryptedText);
}

}

2 个答案:

答案 0 :(得分:3)

根据您的评论,您非常接近加密工作。

您需要将IV生成代码从加密/解密方法移动到其他地方,就像这样

public AlgorithmParameterSpec getIV() {
AlgorithmParameterSpec ivspec;
byte[] iv = new byte[cipher.getBlockSize()];
new SecureRandom().nextBytes(iv);
ivspec = new IvParameterSpec(iv);
}

然后将ivspec传递给加密和解密方法(使它们看起来像encrypt(String,AlgorithmParameterSpec)),这样你就可以使用相同的iv进行加密和解密。

另外,请勿在decryptedByteArray上调用printBase64Binary,而是调用new String(decryptedByteArray, "UTF-8")

答案 1 :(得分:0)

您有两个问题,首先将输出编码为十六进制字符串,但不要在解码方法中对其进行解码。其次,您生成随机IV,但不要再次使用它进行解码。

public byte[] encrypt(String plainText) throws Exception {
   byte[] iv = new byte[cipher.getBlockSize()];    
   AlgorithmParameterSpec spec = new IvParameterSpec(iv);
   cipher.init(Cipher.ENCRYPT_MODE, key, spec);
   return cipher.doFinal(plainText.getBytes());
}

public String decrypt(byte[] cryptedText) throws Exception {
   byte[] iv = new byte[cipher.getBlockSize()];
   AlgorithmParameterSpec spec = new IvParameterSpec(iv);
   cipher.init(Cipher.DECRYPT_MODE, key, spec);
   // decrypt the message
   byte[] decrypted = cipher.doFinal(cryptedText);
   decryptedText = new String(decrypted, "UTF-8");
   return decryptedText;
}



String decryptedText = aes.decrypt(aes.encrypt(message)).toString();