在NodeJS(Crypto)中实现DES解密:Java转NodeJS遇乱码求助
Java PBEWithMD5AndDES解密转NodeJS实现的问题排查与解决
原Java解密代码
public static String decrypt (String value) { PBEParameterSpec pbeParamSpec = new PBEParameterSpec(SALT, COUNT); PBEKeySpec pbeKeySpec = new PBEKeySpec(KEY); SecretKeyFactory keyFac = SecretKeyFactory.getInstance(SECRET_KEY); SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec); Cipher dcipher = Cipher.getInstance(SECRET_KEY); dcipher.init(Cipher.DECRYPT_MODE, pbeKey, pbeParamSpec); byte[] dec = new sun.misc.BASE64Decoder().decodeBuffer(value); byte[] utf8 = dcipher.doFinal(dec); return new String(utf8, UTF8); }
注:原代码中SECRET_KEY变量名具有误导性,实际代表加密算法PBEWithMD5AndDES,而非密钥内容。
最初的NodeJS错误实现
function decrypt(input) { const encrypted = Buffer.from(input, 'base64') const key = crypto.pbkdf2Sync(SECRET_KEY, salt, ITERATION_COUNT, SECRET_KEY.length, 'md5'); const cipher = crypto.createDecipher('des-cbc', key); const decrypted = Buffer.concat([cipher.update(encrypted, 'base64'), cipher.final()]) return decrypted.toString('utf-8'); }
问题排查
- 算法匹配错误:Java的
PBEWithMD5AndDES是基于口令的加密算法,会从口令、盐、迭代次数派生DES密钥和CBC模式的IV;NodeJS直接用createDecipher('des-cbc', key)未正确处理IV派生,导致解密时IV不匹配,出现乱码。 - 密钥长度错误:DES密钥固定为8字节(56位有效位),原代码用
SECRET_KEY.length作为密钥长度参数是错误的,应指定为8。 - 编码处理错误:
cipher.update(encrypted, 'base64')属于重复解码,encrypted已经是Base64解码后的Buffer,直接传入即可。 - 参数对应混淆:Java中的
KEY是口令字符串,对应NodeJS中PBKDF2的第一个参数;SALT是盐值字节数组,COUNT是迭代次数,需和Java端完全一致。
修正后的NodeJS实现
const crypto = require('crypto'); function decrypt(input, password, salt, iterationCount) { // 解码Base64加密内容 const encryptedData = Buffer.from(input, 'base64'); // 用PBKDF2派生密钥和IV:PBEWithMD5AndDES从MD5哈希中提取前8字节为DES密钥,后8字节为IV const derived = crypto.pbkdf2Sync(password, salt, iterationCount, 16, 'md5'); const key = derived.slice(0, 8); const iv = derived.slice(8, 16); // 创建DES-CBC解密器并指定IV const decipher = crypto.createDecipheriv('des-cbc', key, iv); // 执行解密 let decrypted = decipher.update(encryptedData); decrypted = Buffer.concat([decrypted, decipher.final()]); // 转UTF-8字符串返回 return decrypted.toString('utf8'); }
说明
需确保传入的password对应Java中的KEY(口令字符串),salt对应Java中的SALT(字节数组),iterationCount对应Java中的COUNT,三者必须和Java端完全一致才能正确解密。
内容的提问来源于stack exchange,提问作者niyasc
相关产品推荐
相关产品推荐

