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

在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 17:31:15