Java AES/GCM加密字符串,Dart端解密出现乱码问题求助
问题排查与解决
核心问题:AES/GCM模式的认证标签处理不当
AES/GCM是带认证的加密模式,加密输出包含密文 + 认证标签(默认标签长度16字节)。你的乱码问题大概率是两端对标签的处理不一致,具体分两种情况:
1. Java端未正确拼接认证标签
Java中使用AES/GCM/NoPadding时,Cipher.doFinal()返回的字节数组是密文和标签的拼接结果,而非单独的密文。如果你的Java代码只把12字节IV和密文(丢弃了标签)拼接后Base64编码,Dart端解密时会因缺少认证标签导致逻辑异常,输出乱码。
正确的Java加密流程示例:
// 生成12字节随机IV byte[] iv = new byte[12]; new SecureRandom().nextBytes(iv); // 初始化GCM加密器 Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding"); GCMParameterSpec spec = new GCMParameterSpec(128, iv); // 128位=16字节标签 cipher.init(Cipher.ENCRYPT_MODE, secretKey, spec); // 加密后得到【密文+标签】的字节数组 byte[] ciphertextWithTag = cipher.doFinal(plaintext.getBytes(StandardCharsets.UTF_8)); // 拼接IV + 密文+标签,再Base64编码 byte[] finalBytes = new byte[12 + ciphertextWithTag.length]; System.arraycopy(iv, 0, finalBytes, 0, 12); System.arraycopy(ciphertextWithTag, 0, finalBytes, 12, ciphertextWithTag.length); return Base64.getEncoder().encodeToString(finalBytes);
2. Dart端未正确拆分IV、密文和标签
如果Java端已经正确拼接了IV(12字节) + 密文 + 标签(16字节),但Dart端没有按长度拆分标签,而是把整个解码后的字节当成IV+密文处理,就会导致解密时传入的密文包含标签,最终输出乱码。
正确的Dart解密代码(encrypt:^5.0.3):
import 'package:encrypt/encrypt.dart'; import 'dart:convert'; String decryptAesGcm(String base64Data, String base64Key) { final key = Key.fromBase64(base64Key); final decodedBytes = base64Decode(base64Data); // 按长度拆分:前12字节是IV,最后16字节是标签,中间是密文 final iv = IV(decodedBytes.sublist(0, 12)); final ciphertext = decodedBytes.sublist(12, decodedBytes.length - 16); final tag = decodedBytes.sublist(decodedBytes.length - 16); final encrypter = Encrypter(AES(key, mode: AESMode.gcm)); // GCM模式必须传入tag参数 final plaintext = encrypter.decrypt(Encrypted(ciphertext), iv: iv, tag: tag); return plaintext; }
额外排查点:字符编码一致性
确保Java端加密时用UTF-8将字符串转字节数组(plaintext.getBytes(StandardCharsets.UTF_8)),Dart端解密后默认用UTF-8转字符串,避免因编码不一致导致乱码。
内容的提问来源于stack exchange,提问作者AAP
相关产品推荐
相关产品推荐

