You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android生物识别AES加密正常但解密抛出IllegalBlockSizeException求助

问题根因

1. 初始化向量(IV)未持久化,取值错误

AES-CBC模式要求解密必须使用加密阶段生成的同一个IV,你的代码仅将IV存储在类的成员变量initVector中,存在以下问题:

  • 应用重启、单例对象被回收时,initVector会被清空
  • 多次调用加密方法时,后生成的IV会覆盖之前的IV,解密旧数据时IV不匹配
  • 加密结果仅存储了密文,没有和IV绑定存储,跨场景解密时完全无法获取正确的IV
    IV错误会直接导致解密后的块长度不符合要求,触发IllegalBlockSizeException。

2. 密钥读取逻辑错误

getOrCreateSecreteKey方法中,当密钥不存在调用generateSecretKey生成新密钥后,没有重新从KeyStore读取生成好的密钥,直接返回了null,会导致后续加解密拿到空密钥,抛出异常。

3. 单例模式下的IV冲突

使用单例存储全局IV,多业务场景同时加解密时,IV会被互相覆盖,导致解密失败。


修复方案

核心思路

加密时将生成的IV和密文拼接后再做Base64编码存储,解密时先从Base64解码后的字节数组前16位取出IV,剩余部分作为密文解密,不需要额外存储IV变量,同时修复密钥读取逻辑。

修复后的代码修改点

  1. 修复密钥读取逻辑
private SecretKey getOrCreateSecreteKey(String aliasKeyName) {
    try {
        KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE);
        keyStore.load(null);
        SecretKey key = ((SecretKey)keyStore.getKey(aliasKeyName, null));
        if(key == null){
            // 生成密钥后重新读取返回
            generateSecretKey(aliasKeyName);
            key = ((SecretKey)keyStore.getKey(aliasKeyName, null));
        }
        return key;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
  1. 修改加密方法,拼接IV和密文
public String encryptData(String info, Cipher cipher){
    try {
        byte[] encryptedData = cipher.doFinal(info.getBytes("UTF-8"));
        byte[] iv = cipher.getIV();
        // 拼接规则:前16位是IV,后续字节为密文
        byte[] combined = new byte[iv.length + encryptedData.length];
        System.arraycopy(iv, 0, combined, 0, iv.length);
        System.arraycopy(encryptedData, 0, combined, iv.length, encryptedData.length);
        return Base64.encodeToString(combined, Base64.NO_WRAP);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
  1. 修改解密方法,先拆分IV再解密
public String decryptData(String stringToDecrypt, String aliasKeyName){
    try {
        byte[] combined = Base64.decode(stringToDecrypt, Base64.NO_WRAP);
        // 拆分前16位为IV
        IvParameterSpec ivSpec = new IvParameterSpec(combined, 0, 16);
        // 读取密钥初始化解密Cipher
        KeyStore keyStore = KeyStore.getInstance(ANDROID_KEY_STORE);
        keyStore.load(null);
        SecretKey secretKey = ((SecretKey)keyStore.getKey(aliasKeyName, null));
        Cipher cipher = getCipher();
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
        // 解密16位之后的密文部分
        byte[] decryptedData = cipher.doFinal(combined, 16, combined.length - 16);
        return new String(decryptedData, StandardCharsets.UTF_8);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
  1. 可删除全局的initVector成员变量,以及原解密方法中读取该变量初始化IV的逻辑,避免取值错误。

内容的提问来源于stack exchange,提问作者Neo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 00:15:03