Android Kotlin实现CryptoJS.AES加密结果与JS端不一致问题咨询
问题根因排查
核心错误点
- 字节转换逻辑完全不匹配
JS端所有输入(密钥、IV、明文)都是直接将原始字符串转为UTF-8编码的原始字节参与加密,而Kotlin端额外做了一次字节转十六进制字符串的操作,再把十六进制字符串的字符转为字节输入,相当于输入内容和JS端完全不一致。例如原始字节为0x9f,转十六进制字符串得到"9f",再转字节就是0x39、0x66两个完全不同的字节,加密结果必然不同。 - 密钥截取逻辑错误
JS端配置keySize:16对应AES-128,要求密钥是16字节原始UTF-8字节。Kotlin端先把原始密钥转成两倍长度的十六进制字符串,再截取前16字节,实际参与加密的密钥和JS端完全不匹配。 - IV生成逻辑错误
JS端IV是取UTC ISO时间前16位字符的UTF-8编码(固定16字节),Kotlin端先把时间字节转十六进制字符串再取前16字节,IV内容和JS端完全不一致。
修复后的Kotlin实现代码
// 直接取原始密钥的UTF-8字节,不要转十六进制 val keyBytes = getSecretKey().toByteArray(Charsets.UTF_8) // 生成和JS逻辑完全一致的IV:UTC ISO时间前16位的UTF-8字节 val piv = Instant.now().toString().substring(0, 16) val ivBytes = piv.toByteArray(Charsets.UTF_8) // 明文和JS逻辑对齐:piv拼接用户凭证后的UTF-8字节 val msgBytes = (piv + userCredentials).toByteArray(Charsets.UTF_8) // 初始化Cipher,部分Android低版本PKCS7Padding可替换为PKCS5Padding,二者对AES兼容 val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding") val keySpec = SecretKeySpec(keyBytes, 0, 16, "AES") val ivParameterSpec = IvParameterSpec(ivBytes) cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivParameterSpec) val encryptResult = cipher.doFinal(msgBytes) // 输出Base64格式和CryptoJS.encrypt的默认输出格式完全匹配 return Base64.getEncoder().encodeToString(encryptResult)
额外校验点
- 确认JS端
getSecretKey()返回的字符串长度至少16位,密钥截取规则两端完全对齐 - 确认两端UTC时间生成逻辑无时区、毫秒级差异,避免IV内容不一致
- 确认JS端最终输出的是
encrypted.toString(),和Kotlin端输出的Base64格式匹配
内容的提问来源于stack exchange,提问作者Ahmad Shahwaiz
相关产品推荐
相关产品推荐

