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

如何在Flutter Dart中解密NestJS AES-256-CTR加密字符串?

问题分析与解决

核心错误点

你的Flutter解密代码存在三个关键问题,导致了"Input data length must be a multiple of cipher's block size"错误:

  • 密钥未经过scrypt推导:JS代码里的密钥是通过scrypt(secretKey, 'salt', 32)生成的32字节密钥,而你直接把原始的secretKey用fromUtf8当作密钥,完全跳过了scrypt推导步骤。
  • IV的编码方式错误:JS里的IV是将字符串q2Q@w3W#转成hex得到7132514077335723,所以Flutter里应该用IV.fromHex()解析这个hex字符串,而不是fromUtf8(后者会把hex字符串当成普通UTF-8字符处理,得到错误的字节序列)。
  • 密文解码方式错误:JS输出的密文是hex格式,但你用了decrypt64(用于Base64编码的密文),应该先把hex密文转成字节数组,再用decrypt方法。

修正后的代码

首先添加依赖到pubspec.yaml:

dependencies:
  encrypt: ^5.0.3
  crypto: ^3.0.3 # 用于scrypt密钥推导

然后修改解密函数:

import 'package:encrypt/encrypt.dart';
import 'package:crypto/crypto.dart';
import 'dart:convert';

void decrypt() {
  try {
    // 1. 用scrypt推导32字节密钥,和JS逻辑完全对齐
    final secretKey = 'H4WtkvK4qyehIe2kjQfH7we1xIHFK67e';
    final salt = utf8.encode('salt');
    // scrypt参数和Node.js默认值保持一致:N=1<<14, r=8, p=1
    final keyBytes = scrypt(utf8.encode(secretKey), salt, 32, N: 1 << 14, r: 8, p: 1);
    final ivKey = Key(keyBytes);

    // 2. 从hex字符串解析IV,确保字节序列和JS一致
    final ivHex = "7132514077335723";
    final iv = IV.fromHex(ivHex);

    // 3. 将hex格式的密文转成字节数组,再执行解密
    final encryptedHex = "222ef6e4c66c3dfdea9cf1f4828f436e";
    final encryptedBytes = hex.decode(encryptedHex);
    final encrypter = Encrypter(AES(ivKey, mode: AESMode.ctr));
    
    final String decrypted = encrypter.decrypt(Encrypted(encryptedBytes), iv: iv);
    setState(() {
      text = decrypted;
    });
  } catch (e) {
    debugPrint(e.toString());
  }
}

关键注意事项

  • scrypt的参数必须和Node端保持一致,否则生成的密钥会不同,导致解密失败。
  • CTR模式本身不需要填充,但错误的密钥/IV/密文格式会触发块大小不匹配的错误,本质是因为输入的字节序列不符合解密要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 05:17:10