Android KeyStore存储密码后解码遇javax.crypto.IllegalBlockSizeException异常
你说得没错,AES这类分组密码的解密输入确实必须是块大小(16字节)的整数倍,你遇到的IllegalBlockSizeException就是因为解码后的44字节数组不符合这个要求。咱们一步步排查和解决:
先核对加密环节的填充配置
这是最常见的原因:如果加密时你用了NoPadding模式,那必须保证明文长度是16的倍数,否则加密后的字节数组长度就会不对;如果用的是Android默认的PKCS7Padding(大部分场景推荐用这个),Cipher会自动给明文补全到16的倍数,解密时也需要对应使用相同的填充方式。
举个正确的加密初始化例子:// 加密时的Cipher初始化,默认使用PKCS7Padding cipher.init(Cipher.ENCRYPT_MODE, yourKeyStoreKey);要是加密时错误指定了
NoPadding但明文长度不达标,那加密后的内容本身就有问题,解密自然会报错。检查Base64编解码的参数一致性
你解密时用了Base64.NO_WRAP,那加密时的Base64编码也得用同样的参数。如果加密时用了Base64.DEFAULT(带换行符),解密时用NO_WRAP就可能导致解码不完整,得到的字节数组长度异常。建议加密和解密统一用相同的Base64参数。确认密钥与算法参数的一致性
如果你的加密用了CBC模式(Android KeyStore的AES默认可能用这个),那加密时生成的IV向量必须在解密时传入。要是解密时没传正确的IV,不仅解密结果会乱码,也可能触发块大小相关的异常。正确的做法是:// 加密时保存IV byte[] iv = cipher.getIV(); // 把IV和加密后的内容一起存储(比如拼接后再Base64编码) // 解密时用保存的IV初始化Cipher IvParameterSpec ivSpec = new IvParameterSpec(savedIvBytes); cipher.init(Cipher.DECRYPT_MODE, yourKeyStoreKey, ivSpec);另外还要确认解密用的密钥和加密时是同一个,密钥的用途(加密/解密)在KeyStore生成时已经正确配置。
修复当前的44字节数组问题
你可以先尝试用Base64.DEFAULT解码当前的encodedString,看看得到的字节数组长度是否变成16的倍数。同时检查原始的encodedString是否完整,有没有被截断或者修改过——如果字符串本身不完整,解码后的字节数组肯定会有问题。
额外提醒:Android KeyStore的密钥有版本和设备兼容性问题,比如某些旧设备可能不支持某些加密模式,建议你在初始化密钥时明确指定算法参数,比如
KeyGenParameterSpec里配置好加密模式、填充方式等。
内容的提问来源于stack exchange,提问作者abrutsze

