0

我正在从文件中检索文本密码作为输入,并对其应用 AES 加密,然后对其进行解密。当我第一次这样做时,每 5 次有 4 次运行正确(加密解密成功),但有 1 次抛出 BadPaddingException。以下是我写的:

//ABCD is class name
public static void enc(String fileName, String pwd) {
    try {
        Properties prop = new Properties();
        InputStream input = ABCD.class.getClassLoader().getResourceAsStream(fileName);
        prop.load(input);
        input.close();
        URL url = ABCD.class.getClassLoader().getResource(fileName);

        FileOutputStream outputStream = new FileOutputStream(url.getPath());
        KeyGenerator key = KeyGenerator.getInstance("AES");

        key.init(128);
        SecretKey aesKey = key.generateKey();
        String newkey = new  String(Base64.encode(aesKey.getEncoded()).getBytes("UTF-8"));

        Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

        aesCipher.init(Cipher.ENCRYPT_MODE, aesKey);
        byte[] clear = pwd.getBytes("UTF-8");
        byte[] cipher = aesCipher.doFinal(clear);
        String encPwd = new String(cipher);
        prop.setProperty("password", encPwd);
        prop.setProperty("secKey", newkey);
        prop.store(outputStream, null);
        outputStream.close();
    } catch (Exception e) {
        System.out.println(e);
    }
}

public static String dec(Properties prop, String fileName) {

    String decPwd = ABCD.map.get(fileName);
            try {
            String newkey = prop.getProperty("secKey");
            StringBuilder pwd;
            byte[] newkeybuff = Base64.decode(newkey.getBytes("UTF-8"));
            SecretKey key = new SecretKeySpec(newkeyuff, "AES");
            Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            aesCipher.init(Cipher.DECRYPT_MODE, key);
            pwd = new StringBuilder(prop.getProperty("password"));
            byte[] cipher = aesCipher.doFinal(pwd.toString().getBytes());
            decPwd = new String(cipher);
        } catch (Exception e) {
            System.out.println(e);
        }
        ABCD.map.put(fileName, decPwd);
    return decPwd;
}

我需要解决这个问题。在某处,我读到 BadPaddingExcpetion 是由于使用 String 完成的操作而发生的,而不是应该使用实际字节的位置。因此,我将代码更改为以下内容:

public static void enc(String fileName, String pwd) {
    try {
        Properties prop = new Properties();
        InputStream input = ABCD.class.getClassLoader().getResourceAsStream(fileName);
        prop.load(input);
        input.close();
        URL url = ABCD.class.getClassLoader().getResource(fileName);

        FileOutputStream outputStream = new FileOutputStream(url.getPath());
        KeyGenerator key = KeyGenerator.getInstance("AES");

        key.init(128);
        SecretKey aesKey = key.generateKey();

        byte[] newkey=(Base64.encode(aesKey.getEncoded())).getBytes("UTF-8");

        Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");


        aesCipher.init(Cipher.ENCRYPT_MODE, aesKey,new IvParameterSpec(new byte[16]));
        byte[] clear = pwd.getBytes("UTF-8");
        byte[] cipher = aesCipher.doFinal(clear);

        prop.setProperty("password", Arrays.toString(cipher));
        prop.setProperty("secKey", Arrays.toString(newkey));

        prop.store(outputStream, null);
        outputStream.flush();
        outputStream.close();

    } catch (Exception e) {
    System.out.println(e);
}
}

public static String dec(Properties prop, String fileName) {

    String decPwd = ABCD.map.get(fileName);
            try {
            byte[] newkey=prop.getProperty("secKey").getBytes("UTF-8");
            byte[] pwd;


            byte[] newkeybuff = Base64.decode(newkey);
            SecretKeySpec key = new SecretKeySpec(newkeybuff, "AES");

            Cipher aesCipher=Cipher.getInstance("AES/CBC/PKCS5Padding");
            aesCipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(new byte[16]));
            pwd = prop.getProperty("password").getBytes();

            byte[] cipher = aesCipher.doFinal(pwd);

            decPwd=new String(cipher);
            System.out.println("Decrypted pwd " + decPwd);

        } 
        catch (Exception e) {
    System.out.println(e);
}
        ABCD.map.put(fileName, decPwd);

    return decPwd;
}

现在,我收到了 InvalidKeyException。这一次,我读到密钥的大小应该是 16 字节。但我不知道如何应用这个。需要解决这个问题!

4

2 回答 2

0

填充错误通常意味着解密失败。

检查密钥是否为全长(16、24 或 32 字节),IV 是否为全长(16 字节)。如果密钥或 IV 被缩短,它将被填充“某物”并且那个人不一致,那么这种填充没有标准。

getBytes("UTF-8")根据使用的字符,可能会返回不同长度的字节。

用于IVnew IvParameterSpec(new byte[16])是不正确的,IV 应该是一个随机字节。处理 IV 的常用方法是在加密时创建一个随机 IV 并将其添加到加密数据中,它不需要是秘密的,并且通过添加它可以用于解密。

于 2017-02-10T15:09:04.723 回答
0

您应该检查您的 IV(初始化向量),它必须与加密和解密相同。

于 2017-02-10T11:00:17.420 回答