Java AES-256-CBC加密后Node.js解密报错:wrong final block length
Java AES-256-CBC加密后Node.js解密报错:wrong final block length
问题场景
使用Java实现AES-256-CBC加密字符串,再通过Node.js的crypto库解密时,抛出错误:
error:1C80006B:Provider routines::wrong final block length
Java加密代码
import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import java.net.URLEncoder; import java.security.spec.KeySpec; import java.util.Base64; import java.nio.charset.StandardCharsets; public class TestEncrypt { public static String encrypt(String strToEncrypt, String key, byte[] initialVector,String salt) throws Exception{ IvParameterSpec ivspec = new IvParameterSpec(initialVector); SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); KeySpec spec = new PBEKeySpec(key.toCharArray(), salt.getBytes(), 65536, 256); SecretKey tmp = factory.generateSecret(spec); SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivspec); return URLEncoder.encode(Base64.getEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes(StandardCharsets.UTF_8))), StandardCharsets.UTF_8.toString()); } public static byte[] decodeToBase64(String base64Value) { return Base64.getDecoder().decode(base64Value); } public static String encryptData(String StringToEncode, String base256Key, String base256Iv, String salt) throws Exception { String encryptedString = encrypt(StringToEncode, base256Key, decodeToBase64(base256Iv), salt); return encryptedString; } public static void main(String args[]) throws Exception { String originalValue = "hello world"; String encryptedValue = encryptData(originalValue, "TSP88GUiIrX5ZyBWAkvWk7JUMBaSlkVADhEB6gsGS9s=", "ZUCKXBlZT6/SdBxLoEJl0Q==", "ssshhhhhhhhhhh!!!!"); System.out.println("originalValue=" + originalValue); System.out.println("encryptedValue=" + encryptedValue); } }
Node.js原解密代码
const crypto = require('crypto'); const algorithm = 'aes-256-cbc'; const digest = 'sha256'; function decrypt(strToDecrypt, secretKey, salt, initialVector) { const key = crypto.pbkdf2Sync( secretKey, Buffer.from(salt), 65536, 32, digest ); const iv = Buffer.from(initialVector, 'base64'); const decipher = crypto.createDecipheriv(algorithm, key, iv); let decrypted = decipher.update(strToDecrypt, 'base64'); decrypted += decipher.final(); return decrypted; } decrypt('V7qjZNuL%2FKBWRWc3hx1wRw%3D%3D', 'TSP88GUiIrX5ZyBWAkvWk7JUMBaSlkVADhEB6gsGS9s=', 'ssshhhhhhhhhhh!!!!', 'ZUCKXBlZT6/SdBxLoEJl0Q==');
错误原因
Java代码中,加密后的Base64字符串被做了URL编码(URLEncoder.encode),但Node.js解密时直接使用了URL编码后的字符串(比如V7qjZNuL%2FKBWRWc3hx1wRw%3D%3D)进行Base64解码,而%2F、%3D这类URL转义字符不属于合法的Base64字符,导致解密时无法正确解析加密数据,最终抛出块长度错误。
修复后的Node.js解密代码
先对输入的加密字符串做URL解码,再进行解密:
const crypto = require('crypto'); const algorithm = 'aes-256-cbc'; const digest = 'sha256'; function decrypt(strToDecrypt, secretKey, salt, initialVector) { // 先做URL解码,还原原始Base64字符串 const decodedStr = decodeURIComponent(strToDecrypt); const key = crypto.pbkdf2Sync( secretKey, Buffer.from(salt), 65536, 32, digest ); const iv = Buffer.from(initialVector, 'base64'); const decipher = crypto.createDecipheriv(algorithm, key, iv); let decrypted = decipher.update(decodedStr, 'base64'); decrypted += decipher.final(); return decrypted; } // 调用示例 const result = decrypt('V7qjZNuL%2FKBWRWc3hx1wRw%3D%3D', 'TSP88GUiIrX5ZyBWAkvWk7JUMBaSlkVADhEB6gsGS9s=', 'ssshhhhhhhhhhh!!!!', 'ZUCKXBlZT6/SdBxLoEJl0Q=='); console.log(result); // 输出: hello world
内容的提问来源于stack exchange,提问作者williamlee
相关产品推荐
相关产品推荐

