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
相关产品推荐
相关产品推荐

