带有随机盐的Java AES给出了一个错误;javax.crypto.BadPaddingException:给定的最后一个块未正确填充“;

带有随机盐的Java AES给出了一个错误;javax.crypto.BadPaddingException:给定的最后一个块未正确填充“;,java,encryption,Java,Encryption,我正在尝试使用自动生成的Salt运行以下AES加密。但当我尝试解密时,它会抛出一条错误消息。主要的想法是 我有一个获取用户名和密码的窗口。然后,它将使用该密码加密数据。以及当用户想要查看它时。他用密码解密 代码 import org.apache.commons.codec.binary.Base64; public class Decrypts { private static final String password = "haasd"; private static f

我正在尝试使用自动生成的Salt运行以下AES加密。但当我尝试解密时,它会抛出一条错误消息。主要的想法是

我有一个获取用户名和密码的窗口。然后,它将使用该密码加密数据。以及当用户想要查看它时。他用密码解密

代码

import org.apache.commons.codec.binary.Base64;

public class Decrypts {
    private static final String password = "haasd";
    private static final String ALGO = "AES";

    public static String encrypt(String Data) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.ENCRYPT_MODE, key);
        byte[] encVal = c.doFinal(Data.getBytes());
        byte[] encryptedValue = new Base64().encode(encVal);
        String ency = new String(encryptedValue);
        return ency;
    }

    @SuppressWarnings("static-access")
    public static String decrypt(String encryptedData) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.DECRYPT_MODE, key);
        byte[] decordedValue = new Base64().decodeBase64(encryptedData);
        byte[] decValue = c.doFinal(decordedValue);
        String decryptedValue = new String(decValue);
        return decryptedValue;
    }

    private static Key generateKey() throws Exception {

        try {
            String salt;
            int pswdIterations = 65536;
            int keySize = 256;
            salt = generateSalt();
            byte[] saltBytes = salt.getBytes("UTF-8");

            SecretKeyFactory factory = SecretKeyFactory
                    .getInstance("PBKDF2WithHmacSHA1");
            PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes,
                    pswdIterations, keySize);

            SecretKey secretKey = factory.generateSecret(spec);

            Key key = new SecretKeySpec(secretKey.getEncoded(), "AES");
            return key;
        } catch (Exception e) {
            System.out.println(e);
        }
        return null;

    }

    public static String generateSalt() {
        SecureRandom random = new SecureRandom();
        byte bytes[] = new byte[20];
        random.nextBytes(bytes);
        String s = new String(bytes);
        return s;
    }

}
public class Decrypts {
    private static final String password = "haasd";
    private static final String ALGO = "AES";

    public static String encrypt(String Data) throws Exception {
        String SALT = generateSalt();
        byte[] saltBytes = SALT.getBytes("UTF-8");
        System.out.println("Saltbytes ; " + saltBytes);

        SecretKeyFactory factory = SecretKeyFactory
                .getInstance("PBKDF2WithHmacSHA1");
        PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes,
                65536, 256);

        SecretKey secretKey = factory.generateSecret(spec);
        SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.ENCRYPT_MODE, secret);
        byte[] encVal = c.doFinal(Data.getBytes());
        byte[] encryptedValue = new Base64().encode(encVal);
        String ency = new String(encryptedValue);
        return ency;
    }

    @SuppressWarnings("static-access")
    public static String decrypt(String encryptedData) throws Exception {
        String SALT = generateSalt();
        byte[] saltBytes = SALT.getBytes("UTF-8");
        System.out.println("Saltbytes ; " + saltBytes);

        SecretKeyFactory factory = SecretKeyFactory
                .getInstance("PBKDF2WithHmacSHA1");
        PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes,
                65536, 256);

        SecretKey secretKey = factory.generateSecret(spec);
        SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.DECRYPT_MODE, secret);
        byte[] decordedValue = new Base64().decodeBase64(encryptedData);
        byte[] decValue = c.doFinal(decordedValue);
        String decryptedValue = new String(decValue);
        return decryptedValue;
    }

    public static String generateSalt() {
        SecureRandom random = new SecureRandom(password.getBytes());
        byte bytes[] = new byte[120];
        random.nextBytes(bytes);
        String s = new String(bytes);
        System.out.println("Salt ; " + s);
        return s;
    }
}
更新代码

import org.apache.commons.codec.binary.Base64;

public class Decrypts {
    private static final String password = "haasd";
    private static final String ALGO = "AES";

    public static String encrypt(String Data) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.ENCRYPT_MODE, key);
        byte[] encVal = c.doFinal(Data.getBytes());
        byte[] encryptedValue = new Base64().encode(encVal);
        String ency = new String(encryptedValue);
        return ency;
    }

    @SuppressWarnings("static-access")
    public static String decrypt(String encryptedData) throws Exception {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.DECRYPT_MODE, key);
        byte[] decordedValue = new Base64().decodeBase64(encryptedData);
        byte[] decValue = c.doFinal(decordedValue);
        String decryptedValue = new String(decValue);
        return decryptedValue;
    }

    private static Key generateKey() throws Exception {

        try {
            String salt;
            int pswdIterations = 65536;
            int keySize = 256;
            salt = generateSalt();
            byte[] saltBytes = salt.getBytes("UTF-8");

            SecretKeyFactory factory = SecretKeyFactory
                    .getInstance("PBKDF2WithHmacSHA1");
            PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes,
                    pswdIterations, keySize);

            SecretKey secretKey = factory.generateSecret(spec);

            Key key = new SecretKeySpec(secretKey.getEncoded(), "AES");
            return key;
        } catch (Exception e) {
            System.out.println(e);
        }
        return null;

    }

    public static String generateSalt() {
        SecureRandom random = new SecureRandom();
        byte bytes[] = new byte[20];
        random.nextBytes(bytes);
        String s = new String(bytes);
        return s;
    }

}
public class Decrypts {
    private static final String password = "haasd";
    private static final String ALGO = "AES";

    public static String encrypt(String Data) throws Exception {
        String SALT = generateSalt();
        byte[] saltBytes = SALT.getBytes("UTF-8");
        System.out.println("Saltbytes ; " + saltBytes);

        SecretKeyFactory factory = SecretKeyFactory
                .getInstance("PBKDF2WithHmacSHA1");
        PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes,
                65536, 256);

        SecretKey secretKey = factory.generateSecret(spec);
        SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.ENCRYPT_MODE, secret);
        byte[] encVal = c.doFinal(Data.getBytes());
        byte[] encryptedValue = new Base64().encode(encVal);
        String ency = new String(encryptedValue);
        return ency;
    }

    @SuppressWarnings("static-access")
    public static String decrypt(String encryptedData) throws Exception {
        String SALT = generateSalt();
        byte[] saltBytes = SALT.getBytes("UTF-8");
        System.out.println("Saltbytes ; " + saltBytes);

        SecretKeyFactory factory = SecretKeyFactory
                .getInstance("PBKDF2WithHmacSHA1");
        PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes,
                65536, 256);

        SecretKey secretKey = factory.generateSecret(spec);
        SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
        Cipher c = Cipher.getInstance(ALGO);
        c.init(Cipher.DECRYPT_MODE, secret);
        byte[] decordedValue = new Base64().decodeBase64(encryptedData);
        byte[] decValue = c.doFinal(decordedValue);
        String decryptedValue = new String(decValue);
        return decryptedValue;
    }

    public static String generateSalt() {
        SecureRandom random = new SecureRandom(password.getBytes());
        byte bytes[] = new byte[120];
        random.nextBytes(bytes);
        String s = new String(bytes);
        System.out.println("Salt ; " + s);
        return s;
    }
}

encrypt()
decrypt()
中生成随机salt,salt生成将在两种方法中给出不同的salt,因此,如果最后一个块没有正确填充,您将得到错误

事实上,您应该只使用一种您指定的普通盐(固定盐)或随机生成的盐。让我们为它定义一个类变量

private static final String password = "haasd";
private static final String ALGO = "AES";
private static final String SALT = generateSalt(); //generate salt once
然后在您的
generateKey()
中,不要再次生成salt,只需使用类成员
salt

//byte[] saltBytes = salt.getBytes("UTF-8");
byte[] saltBytes = SALT.getBytes("UTF-8"); //using class member SALT
另一种方法是在加密和解密方法中接受用户输入的密码作为参数。然后使用该密码生成salt,如下所示

public static String generateSalt(String password) {
    SecureRandom random = new SecureRandom(password.getBytes());
    ...
}

如果我这样做了,如果我加密同一个单词,不会给出相同的加密值吗?因为密码和salt都是一样的?因为我不会同时解密它。它将存储加密的值,当用户只需要时,它将解密。那么我需要指定salt,对吗?@checkmate基本上是的,在您的情况下,生成的salt对于一对work encrypt()和decrypt()必须是相同的。如果一个单词用salt
a
加密,则该加密文本需要用相同的salt
a
解密。因此,您需要维护生成的salt(在加密时),以备将来使用(在解密时)。无论是在文件系统中保存还是以任何存储库方式保存。嗯,还有其他方法可以使用随机salt进行加密和解密吗?如果有,请在加密和解密中接受用户输入的密码作为arg,并使用固定salt。然后在
new PBEKeySpec()
中使用该密码。Hy,非常感谢您抽出时间。尽管如此,如果密码相同,我仍然会得到相同的加密密钥。我检查了一下,盐和盐没有什么不同。和键总是一样的。检查我编辑的答案。