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

AES带初始化向量加密数据存SQL库后解密报Invalid IV错误求助

问题原因
  • IV存储内容错误:你存入数据库的[B@5a36422是Kotlin/Java中ByteArray调用默认toString()方法的输出,仅为该字节数组对象的内存地址标识,完全不是IV的实际字节内容,解密时传入的是无效IV值,因此触发报错。
  • 加密数据转换错误:AES加密后的结果是二进制字节数组,包含大量不符合UTF-8编码规范的字节,直接用toString(Charsets.UTF_8)转换会发生数据丢失、字符转义,解密时转换回的字节数组和原始加密数据不一致。
  • 密钥生成逻辑错误:你当前getKey()方法每次调用都会执行genKey()生成新密钥,覆盖之前的旧密钥,加密和解密使用的密钥不匹配,就算IV正确也无法解密成功。
修复方案

1. 修复密钥生成逻辑

仅当AndroidKeyStore中不存在对应别名的密钥时才生成新密钥,修改Encrypted类的getKey方法:

fun getKey(): SecretKey {
    val keystore = KeyStore.getInstance("AndroidKeyStore")
    keystore.load(null)
    // 先判断密钥是否已存在,不存在再生成
    if (!keystore.containsAlias("MyKeyAlias")) {
        keyGenerator.init(keyGenParameterSpec)
        keyGenerator.generateKey()
    }
    val secretKeyEntry = keystore.getEntry("MyKeyAlias", null) as KeyStore.SecretKeyEntry
    return secretKeyEntry.secretKey
}
// 同时删除原来getKey方法里调用genKey()的逻辑,genKey()方法可以直接删掉

2. 二进制数据转Base64存储

所有二进制数据(IV、加密结果)不要直接转UTF-8字符串,改为转Base64编码的可打印字符串再存入数据库,修改Encrypted类的加密输出逻辑:

import android.util.Base64

// 加密后输出的部分修改为:
val pair = encryptData(wordE)
// 加密结果转Base64
val encrypted = Base64.encodeToString(pair.second, Base64.DEFAULT)
// IV转Base64
val iv = Base64.encodeToString(pair.first, Base64.DEFAULT)

3. 修复解密逻辑

解密时先把Base64格式的字符串转回原始字节数组,再进行解密操作,修改Decrypted类代码:

import android.util.Base64

fun decryptData(data: String, iv : String) : String {
    // 先把Base64字符串转回原始字节数组
    val ivBytes = Base64.decode(iv, Base64.DEFAULT)
    val encryptedBytes = Base64.decode(data, Base64.DEFAULT)
    
    val spec = IvParameterSpec(ivBytes)
    val decipher = Cipher.getInstance("AES/CBC/NoPadding")

    decipher.init(Cipher.DECRYPT_MODE, getKey(), spec)
    return decipher.doFinal(encryptedBytes).toString(Charsets.UTF_8).trim()
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 02:24:06