如何在Flutter中使用AES-256加密字符串以支持Web端OpenSSL解密
问题根因
AES是国际标准加密算法,所有合规实现的库本身完全兼容,解密失败100%是两端加密参数未完全对齐,常见不匹配点如下:
- 加密模式不一致:encrypt库AES默认使用CBC模式、PKCS7填充,很多在线工具默认会用ECB模式或者不填充,参数不匹配就会解密失败
- 编码格式不匹配:Dart侧输出的密钥、IV、密文默认是base64编码,解密时需要先做base64解码得到原始二进制数据,不能直接把base64字符串当作输入
- 密钥派生逻辑不统一:适配CryptoJS的方案使用了自定义的密钥+盐派生逻辑,服务端如果没有对应实现相同的派生规则,自然无法解密
- IV处理逻辑不同:IV不需要保密,每次加密随机生成即可,加密后需要把IV和密文一起传给服务端,否则服务端拿不到正确的IV无法解密
可直接和PHP OpenSSL互通的实现方案
Dart端(encrypt库)实现
import 'package:encrypt/encrypt.dart'; import 'dart:math'; import 'dart:convert'; // 生成安全随机的32字节AES-256密钥,生产环境密钥提前和后端约定好,不要每次生成 String generateAesKey() { final random = Random.secure(); final keyBytes = List<int>.generate(32, (_) => random.nextInt(256)); return base64Encode(keyBytes); } // AES加密,返回 密文base64:IVbase64 格式的字符串,方便传给后端 String aesEncrypt(String plainText, String base64Key) { final key = Key.fromBase64(base64Key); // 每次加密随机生成16字节IV final iv = IV.fromSecureRandom(16); // 明确指定模式为CBC,填充为PKCS7,和PHP默认参数对齐 final encrypter = Encrypter(AES(key, mode: AESMode.cbc, padding: 'PKCS7')); final encrypted = encrypter.encrypt(plainText, iv: iv); // 把密文和IV用冒号拼接,后端拆分即可 return '${encrypted.base64}:${iv.base64}'; } // 测试用解密方法 String aesDecrypt(String encryptData, String base64Key) { final parts = encryptData.split(':'); if (parts.length != 2) throw Exception('Invalid encrypt data format'); final encrypted = Encrypted.fromBase64(parts[0]); final iv = IV.fromBase64(parts[1]); final key = Key.fromBase64(base64Key); final encrypter = Encrypter(AES(key, mode: AESMode.cbc, padding: 'PKCS7')); return encrypter.decrypt(encrypted, iv: iv); }
PHP端(OpenSSL)解密实现
function aesDecrypt(string $encryptData, string $base64Key): string { $parts = explode(':', $encryptData); if (count($parts) !== 2) throw new Exception('Invalid encrypt data format'); $ciphertext = base64_decode($parts[0]); $iv = base64_decode($parts[1]); // 对应AES-256-CBC模式,和Dart端参数完全对齐 return openssl_decrypt($ciphertext, 'AES-256-CBC', base64_decode($base64Key), OPENSSL_RAW_DATA, $iv); }
在线工具测试注意事项
用在线工具测试时需要选择对应参数:
- 加密模式选CBC
- 填充方式选PKCS7/PKCS5
- 密钥长度选256位
- 输入的密钥、IV都要选base64格式导入,不要直接粘贴字符串
- 密文输入选base64格式
内容的提问来源于stack exchange,提问作者araina1995
相关产品推荐
相关产品推荐

