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

Android使用AES-256-GCM加密带重音文本Node.js解密失败排查

问题根因

这个报错和带重音符号的文本没有直接关系,核心错误出在Android端密文与认证标签的拆分逻辑,非ASCII字符的编码长度差刚好触发了问题:

  • 纯ASCII字符场景下,字符串字符数和UTF-8字节数相等,原有拆分逻辑可以正常运行
  • 带重音的字符、中文等非ASCII字符在UTF-8编码下占2-4字节,此时用字符串长度text.length()(统计字符数)去切分字节数组,会导致密文、GCM认证标签(tag)截取错误,Node.js端拿到无效tag做完整性校验时,就会抛出Unsupported state or unable to authenticate data错误。
    另外如果两端密钥派生参数不对齐,也会触发同类报错。
修复步骤

1. 修正Android端密文与tag的拆分逻辑

原有代码用text.length()作为密文长度判断依据是完全错误的,GCM模式下tag长度是固定值(代码里配置的是128位即16字节),直接从加密结果末尾截取tag即可,不需要依赖原文本长度。
找到encrypt方法里的错误代码:

byte[] ciphertext = Arrays.copyOfRange(cipher, 0, text.length());
byte[] tag = Arrays.copyOfRange(cipher, text.length(), cipher.length);

替换为:

// GCM tag长度为16字节,对应传入GCMParameterSpec的128位tag配置
int tagByteLength = 16;
byte[] ciphertext = Arrays.copyOfRange(cipher, 0, cipher.length - tagByteLength);
byte[] tag = Arrays.copyOfRange(cipher, cipher.length - tagByteLength, cipher.length);

修改后无论原文本包含什么编码的字符,都能正确拆分密文和tag。

2. 对齐两端PBKDF2密钥派生参数

检查Android端getKeyFromPassword方法的参数,必须和Node.js端完全一致:

  • 迭代次数:2145
  • 派生密钥长度:32字节(对应AES-256)
  • 哈希算法:SHA-512
    任意参数不匹配都会导致两端生成的密钥不同,直接触发认证失败。

3. (可选优化)修正Node.js端解密的编码参数

Node.js端update方法传入的text本身是Buffer对象,不需要指定binary输入编码,把解密返回的代码改成:

return decipher.update(text, null, 'utf8') + decipher.final('utf8');
验证说明

修复后使用提供的测试文本Désolé、密钥tIJg9tyj2setkg7gknVreP5PXzRQV5J3测试,GCM认证可以正常通过,解密结果完全正确,不会再抛出认证错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 03:21:45