JS AES CTR加密返回的Uint8Array无法赋值给Java byte[]且解密失败如何处理
问题根因与修正方案
核心问题1:计数器(IV)初始值不匹配
你两端的CTR计数器初始值完全不一致,这是解密失败的最主要原因:
- JS端
new aesjs.Counter(16):aesjs的Counter构造函数传入数值时,会生成16字节的计数器块,默认大端序存储传入的数值,前12字节均为0,最后4字节为0x00000010(对应十进制16),和你Java端写的{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}完全不一样。 - 修正方案:两端统一显式指定16字节IV即可,比如JS端改为:
var aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]));
和Java的ivBytes完全对齐。
核心问题2:Cipher算法配置错误
你没有指定CTR模式必须的无填充配置,SunJCE默认的AES算法可能是AES/ECB/PKCS5Padding,和CTR模式不匹配。
- 修正方案:初始化Cipher时显式指定算法:
Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
同时要确保密钥、IV参数实例化正确:
SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
核心问题3:解密入参错误
你代码中解密调用cipher.doFinal(decoded),但decoded变量未定义,你实际的密文是resp数组,这里属于变量书写错误。
- 修正方案:改为传入resp数组:
byte[] plaintext = cipher.doFinal(resp);
补充说明
你之前将大于127的数值强转为(byte)的操作是正确的:Java的byte是有符号8位整数,范围-128~127,JS的Uint8Array是无符号8位整数,范围0~255,强转后二进制值完全一致,不会影响解密结果。
内容的提问来源于stack exchange,提问作者Tommy Leong
相关产品推荐
相关产品推荐

