NodeJS转Kotlin:CryptoJS.AES.encrypt加密结果不一致求助
问题原因分析
你的Kotlin代码和CryptoJS的AES加密结果不一致,核心是两者在密钥生成方式、加密模式、IV处理这三个关键环节不匹配:
加密模式与填充差异
CryptoJS的AES.encrypt(text, password)默认使用AES-CBC模式+PKCS7填充;而你的Kotlin代码中Cipher.getInstance("AES")默认采用的是ECB模式+PKCS5填充(虽然PKCS5和PKCS7在AES 16字节块大小下兼容,但ECB模式本身无IV,和CBC逻辑完全不同)。密钥与IV的生成逻辑不同
CryptoJS不会直接对密码做SHA-256哈希来生成密钥,而是采用OpenSSL的EVP_BytesToKey算法(基于MD5摘要,迭代1次,无盐),同时生成256位AES密钥和16字节的IV;你的代码直接用SHA-256哈希密码作为密钥,没有生成IV,这是核心差异。输出格式差异
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
相关产品推荐
相关产品推荐

