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

NodeJS转Kotlin:CryptoJS.AES.encrypt加密结果不一致求助

问题原因分析

你的Kotlin代码和CryptoJS的AES加密结果不一致,核心是两者在密钥生成方式、加密模式、IV处理这三个关键环节不匹配:

  1. 加密模式与填充差异
    CryptoJS的AES.encrypt(text, password)默认使用AES-CBC模式+PKCS7填充;而你的Kotlin代码中Cipher.getInstance("AES")默认采用的是ECB模式+PKCS5填充(虽然PKCS5和PKCS7在AES 16字节块大小下兼容,但ECB模式本身无IV,和CBC逻辑完全不同)。

  2. 密钥与IV的生成逻辑不同
    CryptoJS不会直接对密码做SHA-256哈希来生成密钥,而是采用OpenSSL的EVP_BytesToKey算法(基于MD5摘要,迭代1次,无盐),同时生成256位AES密钥和16字节的IV;你的代码直接用SHA-256哈希密码作为密钥,没有生成IV,这是核心差异。

  3. 输出格式差异
    CryptoJS会自动将生成的IV和加密后的密文拼接在一起,再做Base64编码;你的代码仅对密文做Base64,缺少IV部分,导致输出长度更短。

修正后的Kotlin代码
import javax.crypto.Cipher
import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec
import java.security.MessageDigest
import java.util.*

fun encryptAes(text: String, password: String): String {
    // 实现CryptoJS兼容的EVP_BytesToKey算法,生成key和IV
    val passwordBytes = password.toByteArray(Charsets.UTF_8)
    val md5 = MessageDigest.getInstance("MD5")
    var digest = md5.digest(passwordBytes)
    
    // 迭代生成32字节key + 16字节IV(共48字节)
    val keyAndIv = ByteArray(48)
    System.arraycopy(digest, 0, keyAndIv, 0, 16)
    md5.update(digest)
    digest = md5.digest(passwordBytes)
    System.arraycopy(digest, 0, keyAndIv, 16, 16)
    md5.update(digest)
    digest = md5.digest(passwordBytes)
    System.arraycopy(digest, 0, keyAndIv, 32, 16)
    
    val key = keyAndIv.copyOfRange(0, 32)
    val iv = keyAndIv.copyOfRange(32, 48)
    
    // 初始化AES-CBC加密器,PKCS5填充(与CryptoJS的PKCS7兼容)
    val secretKeySpec = SecretKeySpec(key, "AES")
    val ivSpec = IvParameterSpec(iv)
    val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec)
    
    // 加密文本
    val encryptedBytes = cipher.doFinal(text.toByteArray(Charsets.UTF_8))
    
    // 将IV和密文拼接后Base64编码,匹配CryptoJS输出格式
    val combined = ByteArray(iv.size + encryptedBytes.size)
    System.arraycopy(iv, 0, combined, 0, iv.size)
    System.arraycopy(encryptedBytes, 0, combined, iv.size, encryptedBytes.size)
    
    return Base64.getEncoder().encodeToString(combined)
}
关键细节说明
  • EVP_BytesToKey实现:完全对齐CryptoJS默认逻辑,用MD5迭代3次生成32字节密钥和16字节IV。
  • 加密模式:明确指定AES/CBC/PKCS5Padding,和CryptoJS的默认配置一致。
  • 输出拼接:先把IV放在前面,再拼接密文,最后统一Base64,确保输出长度和格式与CryptoJS一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 04:40:23