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

如何让dart:encrypt与crypto-js实现一致的加解密结果?

问题:Dart encrypt包与CryptoJS AES加解密一致性问题

我在Flutter项目中使用Dart的encrypt包实现AES加解密,由于需要在Flutter Web的Web Worker中复用逻辑,尝试改用CryptoJS的vanilla JS版本。目前无法实现两者在同一密钥下的加解密互通,需要解决双向兼容问题:Dart加密后JS能解密,JS加密后Dart能解密。

Dart端代码及运行结果

import 'package:encrypt/encrypt.dart';

void main() {
  final key = Key.fromUtf8("VishnuTestKeyIsHereLongValid32Ch");
  final encrypter = Encrypter(AES(key));
  final iv = IV.fromLength(16); // 生成16字节全0的IV
  var encrypted = encrypter.encrypt("Vishnu", iv: iv);
  print(encrypted.base64); // 输出:8beisXeeEE055QEPq+kumw==
}

当前JS端代码(无法正确解密)

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>
var base64Encrypted = '8beisXeeEE055QEPq+kumw=='
var myKey = "VishnuTestKeyIsHereLongValid32Ch"
var result = CryptoJS.AES.decrypt(base64Encrypted, myKey).toString(CryptoJS.enc.Utf8)

console.log(result); // 无正确输出

问题根源及解决方案

两者无法互通的核心原因是密钥处理、IV配置、加密参数不匹配,具体修正如下:

  1. 统一密钥处理方式:Dart直接将UTF8字符串转为原始密钥;CryptoJS默认会对传入的字符串密钥执行PBKDF2推导,需在JS中直接将字符串转为UTF8格式的密钥,跳过推导步骤。
  2. 统一IV参数:Dart使用16字节全0IV,当前JS未指定IV导致自动生成随机IV,需显式配置相同的全0IV。
  3. 统一加密模式与填充方式:两者默认都是CBC模式+PKCS7填充,建议显式指定参数避免版本差异。

修正后的JS解密代码

var base64Encrypted = '8beisXeeEE055QEPq+kumw==';
var myKey = "VishnuTestKeyIsHereLongValid32Ch";

// 将密钥转为UTF8格式的WordArray
var key = CryptoJS.enc.Utf8.parse(myKey);
// 使用和Dart一致的16字节全0IV
var iv = CryptoJS.enc.Utf8.parse('0000000000000000');

var decrypted = CryptoJS.AES.decrypt(base64Encrypted, key, {
  iv: iv,
  mode: CryptoJS.mode.CBC,
  padding: CryptoJS.pad.Pkcs7
});

console.log(decrypted.toString(CryptoJS.enc.Utf8)); // 输出:Vishnu

JS加密、Dart解密的兼容代码

JS加密代码

var plaintext = "Vishnu";
var myKey = "VishnuTestKeyIsHereLongValid32Ch";
var key = CryptoJS.enc.Utf8.parse(myKey);
var iv = CryptoJS.enc.Utf8.parse('0000000000000000');

var encrypted = CryptoJS.AES.encrypt(plaintext, key, {
  iv: iv,
  mode: CryptoJS.mode.CBC,
  padding: CryptoJS.pad.Pkcs7
});

console.log(encrypted.toString()); // 输出与Dart加密一致的base64字符串

Dart解密JS加密内容的代码

import 'package:encrypt/encrypt.dart';

void main() {
  final key = Key.fromUtf8("VishnuTestKeyIsHereLongValid32Ch");
  final encrypter = Encrypter(AES(key));
  final iv = IV.fromLength(16); // 保持全0IV一致
  // 传入JS加密生成的base64字符串
  var decrypted = encrypter.decrypt(Encrypted.fromBase64("8beisXeeEE055QEPq+kumw=="), iv: iv);
  print(decrypted); // 输出:Vishnu
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 22:15:22