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

Flutter实现兼容Java的AES CBC-128自定义密钥加解密

Flutter 实现与Java逻辑完全一致的AES CBC-128加解密

核心规则对齐(此前实现不匹配的根本原因)

必须1:1对齐Java代码的自定义逻辑,否则加密结果无法匹配:

  • 密钥预处理:将输入密钥转为UTF-8字节数组,新建固定长度16的空字节数组(默认值全0),将原密钥字节复制到该数组,若原密钥长度超过16则截断,不足16则剩余位置保留0值
  • IV取值:直接使用预处理后的16位密钥字节作为IV向量,不生成随机IV
  • 算法配置:AES算法,CBC模式,PKCS5填充(AES块长固定为16字节时,PKCS5与PKCS7填充逻辑完全一致)
  • 编解码规则:加密结果做Base64编码输出,解密前先将输入密文做Base64解码得到原始字节

具体实现步骤

  1. 引入依赖
    在pubspec.yaml的dependencies节点添加以下依赖,该库支持自定义密钥与IV,适配灵活度更高:
dependencies:
  pointycastle: ^3.7.3

执行flutter pub get完成依赖安装,Dart内置dart:convert库原生支持Base64编解码,无需额外引入编解码相关依赖。

  1. 加解密工具代码
import 'dart:convert';
import 'dart:typed_data';
import 'package:pointycastle/export.dart';

class AesCbc128Util {
  /// 对齐Java逻辑的密钥预处理
  static Uint8List _processKeyBytes(String key) {
    final originKeyBytes = utf8.encode(key);
    // 初始化16字节全0数组
    final processedKey = Uint8List(16);
    final copyLength = originKeyBytes.length > 16 ? 16 : originKeyBytes.length;
    // 复制原密钥字节,不足16位的位置保持0值
    processedKey.setRange(0, copyLength, originKeyBytes);
    return processedKey;
  }

  /// 对齐Java Encrypt方法的加密逻辑
  static String encrypt(String plainText, String key) {
    final keyBytes = _processKeyBytes(key);
    // IV直接复用处理后的密钥字节
    final ivBytes = keyBytes;

    // 初始化AES/CBC加密器
    final cipher = PaddedBlockCipherImpl(
      PKCS7Padding(),
      CBCBlockCipher(AESEngine()),
    )..init(
        true,
        PaddedBlockCipherParameters(
          ParametersWithIV(KeyParameter(keyBytes), ivBytes),
          null,
        ),
      );

    final plainBytes = Uint8List.fromList(utf8.encode(plainText));
    final cipherBytes = cipher.process(plainBytes);
    // Base64编码输出密文
    return base64Encode(cipherBytes);
  }

  /// 对齐Java Decrypt方法的解密逻辑
  static String decrypt(String cipherText, String key) {
    final keyBytes = _processKeyBytes(key);
    final ivBytes = keyBytes;

    // 初始化AES/CBC解密器
    final cipher = PaddedBlockCipherImpl(
      PKCS7Padding(),
      CBCBlockCipher(AESEngine()),
    )..init(
        false,
        PaddedBlockCipherParameters(
          ParametersWithIV(KeyParameter(keyBytes), ivBytes),
          null,
        ),
      );

    // 先Base64解码密文再解密
    final cipherBytes = base64Decode(cipherText);
    final plainBytes = cipher.process(cipherBytes);
    return utf8.decode(plainBytes);
  }
}

用例验证

使用给定测试参数调用方法即可得到与Java完全一致的结果:

void main() {
  const testPlain = "This is plain text";
  const testKey = "sahtojetrout2";
  final encrypted = AesCbc128Util.encrypt(testPlain, testKey);
  print(encrypted); // 输出 8FmSMnDsFJVyNUXunhJLSmhFnRq89fl5DyTp0wdYfgk=,与Java结果完全匹配
  final decrypted = AesCbc128Util.decrypt(encrypted, testKey);
  print(decrypted); // 输出 This is plain text
}

之前使用cryptography库实现失败的核心原因是:该库默认会自动生成随机IV,且默认密钥校验逻辑不支持自动截断长密钥、自动补0对齐短密钥,和Java的自定义处理逻辑不兼容,替换为上述实现即可完全对齐两端结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 15:36:21