Node.js解密Android端AES加密字符串时遇最终块长度错误
解决Node.js解密Android AES加密文本时的"wrong final block length"错误
问题根源
你遇到的错误本质是两个关键问题导致的:
1. AES算法版本不匹配
Android的SecretKeySpec会根据密钥的字节长度自动适配AES版本:
- 16字节密钥 → AES-128
- 24字节密钥 → AES-192
- 32字节密钥 → AES-256
但你的Node.js代码直接写死了aes-256-cbc,如果Android实际用的是其他版本(比如AES-128),解密过程就会完全错乱。
2. decipher.update的参数错误
你已经把加密字符串转成了Base64解码后的Buffer:
var messageToDecrypt = Buffer.from(encryptedMessage, "base64");
但调用update时还传了'base64'作为输入编码,这会让Node.js重复解码已经是原始字节的Buffer,直接破坏了加密数据的块结构,最终触发块长度错误。
修正后的代码
const crypto = require('crypto'); function decryptAndroidAes(encryptedMessage) { // 解码Base64为原始加密字节 const cipherBuffer = Buffer.from(encryptedMessage, "base64"); // 密钥、IV必须和Android端完全一致(编码、内容都要匹配) const key = Buffer.from("MY_KEY", "utf8"); const iv = Buffer.from("MY_IV", "utf8"); // 根据密钥长度自动匹配AES版本 let algorithm; switch (key.length) { case 16: algorithm = 'aes-128-cbc'; break; case 24: algorithm = 'aes-192-cbc'; break; case 32: algorithm = 'aes-256-cbc'; break; default: throw new Error('密钥长度不符合AES规范,必须是16/24/32字节'); } const decipher = crypto.createDecipheriv(algorithm, key, iv); // 直接传入Buffer,不需要指定输入编码,输出设为utf8 let plaintext = decipher.update(cipherBuffer, undefined, 'utf8'); // 完成解密拼接 plaintext += decipher.final('utf8'); return plaintext.trim(); }
额外注意点
- 确认
MY_IV的长度是16字节(AES的块大小),Android端的IvParameterSpec要求IV必须和块大小一致,所以你的MY_IV应该是16个UTF-8字符。 - 确保Android端的
toBase64是标准Base64编码(无多余换行、符合RFC 4648),避免解码时出现数据损坏。 - 密钥长度必须严格是16/24/32字节,否则Android端初始化Cipher时也会报错,所以你的
MY_KEY要符合这个要求。
内容的提问来源于stack exchange,提问作者Emonale
相关产品推荐
相关产品推荐

