简体   繁体   English

AES / ECB / PKCS5Padding如何正确填充最后一块?

[英]AES/ECB/PKCS5Padding how to properly pad final block?

I am getting this exception: 我收到此异常:

javax.crypto.BadPaddingException: Given final block not properly padded

The weird thing is that this only happens for certain strings, in a kind of unpredictable manner, so I don't know how to fix it. 奇怪的是,这只会以某种不可预测的方式发生在某些字符串上,所以我不知道如何解决它。

Here is the full Exception: 这是完整的例外:

javax.crypto.BadPaddingException: Given final block not properly padded
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
    at javax.crypto.Cipher.doFinal(Cipher.java:2165)

And here is my code: 这是我的代码:

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

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

public class Crypt {

    private Crypt() {
    }

    public static String encrypt(String key, String toEncrypt) {
        byte[] toEncryptBytes = toEncrypt.getBytes();
        try {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, getKey(key));
            byte[] encrypted = cipher.doFinal(toEncryptBytes);
            return new String(encrypted);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    public static String decrypt(String key, String toDecrypt) {
        try {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, getKey(key));
            byte[] decrypted = cipher.doFinal(toDecrypt.getBytes());
            return new String(decrypted);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    private static SecretKeySpec getKey(String str) {
        byte[] bytes = str.getBytes();
        try {
            MessageDigest sha = MessageDigest.getInstance("SHA-256");
            bytes = sha.digest(bytes);
            bytes = Arrays.copyOf(bytes, 16);
            return new SecretKeySpec(bytes, "AES");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static final void main(String[] args) {
        String key = "KEY123";
        String toEncrypt = "0";
        boolean[] b = new boolean[128];
        for (int i = 0; i < 128; i++) {
            if (test(key, toEncrypt) == false) {
                System.err.println("ERROR with size " + toEncrypt.length());
            } else {
                b[i] = true;
            }
            toEncrypt += "0";
        }

        System.out.println("Following sizes don't work:");
        for (int i = 0; i < b.length; i++) {
            if (!b[i]) {
                System.out.println(i + 1);
            }
        }
    }

    // true = success
    public static boolean test(String key, String toEncrypt) {
        try {
            System.out.print(toEncrypt.length() + ": ");
            String encrypted = encrypt(key, toEncrypt);
            System.out.print(encrypted + "; ");

            String decrypted = decrypt(key, encrypted);
            System.out.println(decrypted);

            if (decrypted == null) {
                return false;
            }

            if (toEncrypt.equals(decrypted)) {
                return true;
            }
            return false;
        } catch (Throwable t) {
            return false;
        }
    }
}

After running this code I get the following output: 运行此代码后,我得到以下输出:

Following sizes don't work:
3
6
10
11
15
18
22
23
27
30
34
35
39
42
46
47
51
54
58
59
63
66
70
71
75
78
82
83
87
90
94
95
99
102
106
107
111
114
118
119
123
126

However, these numbers change when I change the String I want to encrypt., eg when I use "1" instead of "0". 但是,当我更改要加密的字符串时,这些数字也会更改。例如,当我使用“ 1”而不是“ 0”时。

How do I get this to work? 我该如何工作? How do I properly pad the final block? 如何正确填充最后一块?

Thanks in advance. 提前致谢。

You are not feeding the decrypt function the exact output of the encrypt function. 您没有将解密函数的确切输出提供给解密函数。

The encryption produces a byte array. 加密产生一个字节数组。 You however convert this to a String, which will interpret the byte array in some fashion (depending on the platform charset). 但是,您可以将其转换为String,这将以某种方式解释字节数组(取决于平台字符集)。

Either keep the byte array itself, or convert the byte array to a hex String or Base64 String. 保留字节数组本身,或者将字节数组转换为十六进制String或Base64 String。 For example: 例如:

        byte[] encrypted = cipher.doFinal(toEncryptBytes);
        return Base64.getEncoder().encode(encrypted);  // Uses Java 8 java.util.Base64

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在AES / CBC / PKCS5Padding中获取“ BadPaddingException:填充块损坏” - Getting 'BadPaddingException: pad block corrupted' in AES/CBC/PKCS5Padding 解密AES / CBC / PKCS5Padding错误:鉴于未正确填充最终块 - Decrypting of AES/CBC/PKCS5Padding Error: Given final block not properly padded AES / CBC / PKCS5Padding Java加密错误-javax.crypto.BadPaddingException:给定最终块未正确填充 - AES/CBC/PKCS5Padding Java Encrypting Error - javax.crypto.BadPaddingException: Given final block not properly padded 用Java解密/解密“AES / ECB / PKCS5Padding” - En-/decrypt “AES/ECB/PKCS5Padding” in Java Java到ruby的AES / ECB / PKCS5Padding加密 - Java to ruby AES/ECB/PKCS5Padding encryption java.security.NoSuchAlgorithmException:AES / ECB / PKCS5Padding - java.security.NoSuchAlgorithmException: AES/ECB/PKCS5Padding 使用AES / ECB / NoPadding和PKCS5Padding进行加密 - encryption using AES/ECB/NoPadding vs PKCS5Padding 使用AES / CBC / PKCS5Padding正确解密文件-BadPaddingException - Properly decrypting a file using AES/CBC/PKCS5Padding - BadPaddingException 使用AES / ECB / PKCS5Padding加密时无法解密-输入长度必须是16的倍数 - Cannot decrypt when encrypted using AES/ECB/PKCS5Padding - input length must be multiple of 16 出于安全考虑,我可以通过哪种方式替换AES / ECB / PKCS5Padding? - by which i can replace AES/ECB/PKCS5Padding for security concern in android application?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM