如何在Flutter中实现与Java一致的AES解密?解决密钥长度报错
问题:Flutter AES256解密报错「Key length not 128/192/256 bits」
我尝试将Java Spring Boot的AES256解密代码转换为Flutter代码,使用了encrypt库,但运行时出现以下错误:
Key length not 128/192/256 bits.
Java Spring Boot 原解密代码
public static String decryptAES256(String str, String secretKey) throws java.io.UnsupportedEncodingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException { String AES = "AES"; String AES_PADDING = "AES/CBC/PKCS5Padding"; byte[] keyData = java.util.Base64.getDecoder().decode(secretKey); String iv = secretKey.substring(0, 16); SecretKey secureKey = new SecretKeySpec(keyData, AES); Cipher c = Cipher.getInstance(AES_PADDING); c.init(Cipher.DECRYPT_MODE, secureKey, new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8))); byte[] byteStr = Base64.getDecoder().decode(str.getBytes()); return new String(c.doFinal(byteStr), StandardCharsets.UTF_8); }
我写的Flutter错误代码
final encData = codefModel.data!.encData!; final key = en.Key.fromUtf8(decryptKey); final b64key = en.Key.fromUtf8(base64Url.encode(key.bytes)); final iv = en.IV.fromLength(16); final encrypter = en.Encrypter(en.AES(b64key, mode: en.AESMode.cbc)); logger.d(encrypter.decrypt64(encData, iv: iv));
问题分析与修正
原Flutter代码的错误点
- 密钥处理逻辑完全颠倒:Java是直接Base64解码密钥字符串得到原始密钥字节,而你的代码先把密钥转成UTF-8字节再Base64编码,导致密钥长度不符合AES256要求(256位=32字节)。
- IV生成错误:Java是取密钥字符串的前16个字符作为IV,而你的代码生成了随机IV,和原逻辑不匹配。
- 填充方式未明确指定:Java用的是PKCS5Padding,需要在Flutter中指定对应的兼容填充方式。
修正后的Flutter解密代码
import 'dart:convert'; import 'package:encrypt/encrypt.dart' as en; // ... 你的业务代码 ... final encData = codefModel.data!.encData!; final decryptKey = "你的密钥字符串"; // 对应Java的secretKey参数 try { // 1. 处理密钥:Base64解码密钥字符串,和Java逻辑一致 final keyBytes = base64Decode(decryptKey); final key = en.Key(keyBytes); // 2. 处理IV:取密钥字符串的前16个字符转UTF-8字节,和Java逻辑一致 final ivStr = decryptKey.substring(0, 16); final iv = en.IV.fromUtf8(ivStr); // 3. 初始化加密器:CBC模式+PKCS7Padding(和Java的PKCS5Padding在128位块下兼容) final encrypter = en.Encrypter( en.AES( key, mode: en.AESMode.cbc, padding: en.AESPadding.pkcs7, ), ); // 4. 解密:自动处理Base64解码,对应Java的Base64解码步骤 final decryptedText = encrypter.decrypt64(encData, iv: iv); logger.d(decryptedText); } catch (e) { logger.e('解密失败:$e'); }
关键说明
- 密钥正确性:确保
decryptKey是和Java端一致的Base64编码字符串,解码后必须是32字节(256位),否则仍会报密钥长度错误。 - IV一致性:必须严格和Java逻辑保持一致,取密钥字符串的前16位,否则解密结果会乱码或失败。
- 填充兼容性:AES的块大小是128位,PKCS5Padding和PKCS7Padding在此场景下完全兼容,所以用encrypt库的
pkcs7即可。
内容的提问来源于stack exchange,提问作者broheat
相关产品推荐
相关产品推荐

