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

Node.js实现DES加密兼容VB.NET DESCryptoServiceProvider解密

如何用Node.js复刻Visual Basic的DES加密逻辑,兼容原有VB解密代码

我有一套基于DES加密的遗留Visual Basic代码,目前文件的加密解密都在VB中完成。现在需要将加密逻辑迁移到Node.js,但保留原VB的解密代码不变,要求Node.js加密的结果能被原VB代码正常解密。

目前已确认VB代码使用CBC模式、PKCS7填充、无密钥盐值,但对Microsoft DESCryptoServiceProvider的部分细节存在疑问,导致Node.js实现的加密结果与VB不匹配,用VB解密Node.js加密的文件时会抛出Length of the data to decrypt is invalid错误。


现有Visual Basic加密代码

Sub EncryptFile(ByVal sInputFilename As String, _
               ByVal sOutputFilename As String, _
               ByVal sKey As String)

        Dim fsInput As New FileStream(sInputFilename, _
                                    FileMode.Open, FileAccess.Read)
        Dim fsEncrypted As New FileStream(sOutputFilename, _
                                    FileMode.Create, FileAccess.Write)

        Dim DES As New DESCryptoServiceProvider()

        'Set secret key for DES algorithm.
        'A 64-bit key and an IV are required for this provider.
        DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey)

        'Set the initialization vector.
        DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey)

        'Create the DES encryptor from this instance.
        Dim desencrypt As ICryptoTransform = DES.CreateEncryptor()

        'Create the crypto stream that transforms the file stream by using DES encryption.
        Dim cryptostream As New CryptoStream(fsEncrypted, _
                                            desencrypt, _
                                            CryptoStreamMode.Write)

        'Read the file text to the byte array.
        Dim bytearrayinput(CInt(fsInput.Length - 1)) As Byte

        fsInput.Read(bytearrayinput, 0, bytearrayinput.Length)

        'Write out the DES encrypted file.
        cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length)
        cryptostream.Close()

        fsInput.Close()
End Sub

该代码完全使用DESCryptoServiceProvider的默认参数。

对应Visual Basic解密代码

Dim DES As New DESCryptoServiceProvider()

        'Set the secret key for the DES algorithm.
        DES.Key() = ASCIIEncoding.ASCII.GetBytes("12345678")
        'Set the initialization vector.
        DES.IV = ASCIIEncoding.ASCII.GetBytes("12345678")

        Dim fsread As New FileStream(FileLocation, FileMode.Open, FileAccess.Read)

        Dim desdecrypt As ICryptoTransform = DES.CreateDecryptor()

        Dim cryptostreamDecr As New CryptoStream(fsread, desdecrypt, CryptoStreamMode.Read)

        Dim sr As StreamReader = New StreamReader(cryptostreamDecr)

        'We can now read unencrypted text from sr

我尝试的Node.js代码(存在问题)

const crypto = require('crypto');
const fs = require('fs');

let key = new Buffer('12345678', 'ascii')
let iv = new Buffer('12345678', 'ascii');

try {
    const data = fs.readFileSync('blah.txt', { encoding: 'binary' });
    console.log(data);

    let cipher = crypto.createCipheriv('des-cbc', key, iv);

    let c = cipher.update(data, 'binary', 'binary');
    
    c += cipher.final('binary');

    fs.writeFileSync('blah.des', c)
}
catch (err) {
    console.error(err);
}

问题分析与解决方案

核心问题

原Node.js代码使用binary编码处理文件数据,这会导致字节转换异常——Node.js的binary编码实际对应latin1,与VB直接读取原始文件字节的方式不一致,最终导致加密后的数据长度不符合DES的块要求(必须是8字节的倍数),触发VB解密时的长度错误。

另外,你提到的密钥迭代次数是误解:VB代码并未使用密码派生函数(如PasswordDeriveBytes),而是直接将ASCII字符串转换为字节数组作为密钥和IV,因此不需要迭代次数。

修正后的Node.js代码

直接操作原始字节(Buffer),避免编码转换导致的字节丢失:

const crypto = require('crypto');
const fs = require('fs');

// 用Buffer.from替代已废弃的new Buffer
const key = Buffer.from('12345678', 'ascii');
const iv = Buffer.from('12345678', 'ascii');

try {
    // 读取文件原始字节,不指定编码,直接得到Buffer
    const rawData = fs.readFileSync('blah.txt');
    
    // 创建DES-CBC加密器,默认使用PKCS7填充(与VB默认一致)
    const cipher = crypto.createCipheriv('des-cbc', key, iv);
    
    // 直接处理Buffer,拼接update和final的结果
    const encryptedBuffer = Buffer.concat([cipher.update(rawData), cipher.final()]);
    
    // 写入加密后的原始字节
    fs.writeFileSync('blah.des', encryptedBuffer);
} catch (err) {
    console.error(err);
}

关键匹配点验证

  • 加密模式:VB的DESCryptoServiceProvider默认使用CBC模式,与Node.js的des-cbc一致。
  • 填充方式:VB默认使用PKCS7填充,Node.js crypto模块的des-cbc默认填充也是PKCS7(OpenSSL中称为PKCS5,但对于8字节块的DES来说两者等价)。
  • 密钥/IV处理:两者均使用ASCII编码将字符串转换为8字节的密钥和IV,完全匹配。
  • 数据处理:修正后的代码直接读取文件原始字节,与VB读取字节数组的逻辑一致,避免了编码转换的误差。

内容的提问来源于stack exchange,提问作者Mark

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 13:57:52