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

VB中Asc与JS中charCodeAt的差异及解密兼容问题排查

VB ASCII加密内容转NodeJS解密的编码适配方案

问题背景

旧系统通过Visual Basic实现加密逻辑:文件存储密钥、加密用户名、加密密码三行内容;解密时先反转加密字符串,将每个字符的编码值减去对应循环位置的密钥字符编码值,最终得到明文。迁移到NodeJS后端后,使用charCodeAt()获取字符编码时出现异常:预期加密字符编码为136(减去密钥编码36后得到明文编码100),但实际拿到8221,导致解密结果完全错误。

根因分析

  • VB的Asc()函数返回的是**ASCII/扩展ASCII(0-255)**数值,对应Windows默认的Windows-1252编码字节值;
  • JS的charCodeAt()返回的是Unicode码点,对于VB中的扩展ASCII字符(128-255),JS会将其解析为Unicode中对应的字符(比如8221是Unicode的右双引号),两者数值完全不匹配。

原VB解密核心代码

Function Decrypt(inputStr As String, key As String) As String
    Dim reversedStr As String
    Dim result As String
    Dim i As Integer
    Dim inputCharCode As Integer
    Dim keyCharCode As Integer
    
    reversedStr = StrReverse(inputStr)
    result = ""
    For i = 1 To Len(reversedStr)
        inputCharCode = Asc(Mid(reversedStr, i, 1))
        keyCharCode = Asc(Mid(key, ((i - 1) Mod Len(key)) + 1, 1))
        result = result & Chr(inputCharCode - keyCharCode)
    Next i
    Decrypt = result
End Function

错误的NodeJS尝试代码

// 问题点:charCodeAt获取Unicode码点,与VB的Asc值不匹配
function decryptWrong(inputStr, key) {
    const reversedStr = inputStr.split('').reverse().join('');
    let result = '';
    for (let i = 0; i < reversedStr.length; i++) {
        const inputCharCode = reversedStr.charCodeAt(i);
        const keyCharCode = key.charCodeAt(i % key.length);
        result += String.fromCharCode(inputCharCode - keyCharCode);
    }
    return result;
}

修正后的NodeJS解密实现

利用NodeJS的Buffer将字符串按Windows-1252编码转换为字节数组,直接操作字节值(对应VB的Asc返回值),解决编码差异问题:

function decryptCorrect(inputStr, key) {
    // 将加密字符串转为Windows-1252编码的字节数组
    const inputBuffer = Buffer.from(inputStr, 'win1252');
    // 反转字节数组(对应VB的StrReverse)
    const reversedBuffer = inputBuffer.reverse();
    // 密钥同样转为Windows-1252字节数组
    const keyBuffer = Buffer.from(key, 'win1252');
    const keyLen = keyBuffer.length;

    const resultBuffer = Buffer.alloc(reversedBuffer.length);
    for (let i = 0; i < reversedBuffer.length; i++) {
        const inputByte = reversedBuffer[i];
        const keyByte = keyBuffer[i % keyLen];
        // 处理可能的负数结果,确保字节值在0-255范围内
        const decryptedByte = (inputByte - keyByte + 256) % 256;
        resultBuffer[i] = decryptedByte;
    }

    // 将解密后的字节数组转回字符串
    return resultBuffer.toString('win1252');
}

验证示例

假设加密文件内容:

testkey
äöü
çåì

预期解密结果:

username
password

使用修正后的代码可得到符合预期的明文,原异常场景中的8221会被转换为1252编码下的136,减去密钥的36后得到100(对应字符'd'),完全匹配VB的解密逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 23:10:25