java - 使用 AES 缓存用户密码 -- BadPaddingException

标签 java encryption aes

我想要一个安全的解决方案,用于在 session 期间在用户的 PC 上缓存用户的密码。

我已经搜索了许多 AES 示例,并且知道这已经在其他地方得到了解答,但我必须说这有点令人困惑。我的 aesSecretKeyaesInitializationVector 无法正确解密,但不确定问题出在哪里。

解密会导致javax.crypto.BadPaddingException:给定最终 block 未正确填充异常。

我的类(class)是这样的

public class LockManagerTest {
    // Need to share the IV and key between encode and decode
    private static byte[] aesInitialisationVector;
    private static SecretKey aesSecretKey;
    private static Cipher aesCipher;

    public LockManagerTest(String sessionKey) {
        try {
            byte[] key = getSecretKey(sessionKey.toCharArray(), getSalt(32),
                                      65536, 128);
            aesSecretKey = new SecretKeySpec(key, "AES");
            aesCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            aesCipher.init(Cipher.ENCRYPT_MODE, aesSecretKey);
            AlgorithmParameters params = aesCipher.getParameters();
            aesInitialisationVector =
                    params.getParameterSpec(IvParameterSpec.class).getIV();
        } catch (Exception e) {
            Util.handleException(e);
        }
    }

    private static byte[] getSecretKey(char[] plaintext,
                                       byte[] salt,
                                       int iterations,
                                       int keySize)
            throws Exception {
        PBEKeySpec spec = new PBEKeySpec(plaintext, salt, iterations, keySize);
        SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        return skf.generateSecret(spec).getEncoded();
    }

    private static byte[] getSalt(int keyLength) throws Exception {
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
        byte[] salt = new byte[keyLength];
        random.nextBytes(salt);
        return salt;
    }

    public byte[] encryptedAes(char[] input) throws Exception {
        // WRONG
        // aesCipher.init(Cipher.ENCRYPT_MODE, aesSecretKey);
        //
        aesCipher.init(Cipher.ENCRYPT_MODE, aesSecretKey, 
                       new IvParameterSpec(aesInitialisationVector);
        CharBuffer cBuf = CharBuffer.wrap(input);
        byte[] normalised = Charset.forName("UTF-8").encode(cBuf).array();
        byte[] ciphertext = aesCipher.doFinal(normalised);
        return ciphertext;
    }

    public byte[] decryptAes(byte[] ciphertext) throws Exception {
        aesCipher.init(Cipher.DECRYPT_MODE,
                aesSecretKey, new IvParameterSpec(aesInitialisationVector));
        byte[] plaintext = aesCipher.doFinal(ciphertext);
        return plaintext;
    }
}

有关安全级别的评论也值得赞赏。

最佳答案

encryptedAes()中调用init()时需要传递IV。

关于java - 使用 AES 缓存用户密码 -- BadPaddingException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18524027/

相关文章:

python - 为什么在读取字节时会得到一个额外的 b 前缀?

java - 如何在字符移位后读取和打印字符串的整个输入?

javascript - 使用 Crypto.JS 解密 AES 加密的二进制文件

sql-server-2008 - SQL Server TDE - 如何判断何时完成?

java - 在任何浏览器中加载 EToken 证书

java - 如何在 java 中使用 selenium webdriver 来查找输入字段是否为只读

java - 如何在selenium java中找到复杂(父子)xpath

java - 带有 NTLM 的 CXF SOAP 客户端到 SharePoint

java - 我们如何知道哪个登录用户正在使用java中的表单?

java - 加密/解密(使用 AES)大文件并通过 HTTP 传输