如何将ROBLOX Lua轻量加密代码及('%02x'):format写法转换为Node.js实现
Roblox Lua轻量加密算法Node.js迁移方案
核心问题解决
你调试失败的核心语法("%02x"):format(c)是Lua中将0-255整数转为两位小写十六进制字符串的内置方法,Node.js中等效实现为:
(c & 0xff).toString(16).padStart(2, '0')
额外加& 0xff是为了兼容JavaScript取模运算可能返回负数的特性,保证输入数值始终落在0-255的合法区间,和Lua端输出结果完全一致。
注意事项
- Lua默认支持大整数运算,Node.js中普通Number类型超过2^53会丢失精度,因此所有涉及密钥K的运算需要用BigInt类型实现,否则加密/解密结果会和Lua端不匹配
- inv256预生成逻辑和Lua端完全一致,可提前生成缓存避免重复计算
原Lua完整实现代码
local Key53 = 8186484168865098 local Key14 = 4887 local inv256 function encode(str) if not inv256 then inv256 = {} for M = 0, 127 do local inv = -1 repeat inv = inv + 2 until inv * (2*M + 1) % 256 == 1 inv256[M] = inv end end local K, F = Key53, 16384 + Key14 return (str:gsub('.', function(m) local L = K % 274877906944 -- 2^38 local H = (K - L) / 274877906944 local M = H % 128 m = m:byte() local c = (m * inv256[M] - (H - M) / 128) % 256 K = L * F + H + c + m return ('%02x'):format(c) end )) end function decode(str) local K, F = Key53, 16384 + Key14 return (str:gsub('%x%x', function(c) local L = K % 274877906944 -- 2^38 local H = (K - L) / 274877906944 local M = H % 128 c = tonumber(c, 16) local m = (c + (H - M) / 128) * (2*M + 1) % 256 K = L * F + H + c + m return string.char(m) end )) end
等效Node.js完整实现代码
const Key53 = 8186484168865098n; const Key14 = 4887n; const F = 16384n + Key14; const POW_2_38 = 274877906944n; // 预生成inv256表,和Lua逻辑完全一致 const inv256 = new Array(128); for (let M = 0; M < 128; M++) { let inv = -1; do { inv += 2; } while ((inv * (2 * M + 1)) % 256 !== 1); inv256[M] = inv; } /** * 加密方法,和原Lua encode输出完全一致 * @param {string} str 待加密的明文字符串 * @returns {string} 十六进制密文字符串 */ function encode(str) { let K = Key53; let result = ''; for (let i = 0; i < str.length; i++) { const m = str.charCodeAt(i); const L = K % POW_2_38; const H = (K - L) / POW_2_38; const M = Number(H % 128n); const c = (m * inv256[M] - Number((H - BigInt(M)) / 128n)) % 256; // 核心转换逻辑,等效Lua的("%02x"):format(c) const cHex = (c & 0xff).toString(16).padStart(2, '0'); result += cHex; K = L * F + H + BigInt(c & 0xff) + BigInt(m); } return result; } /** * 解密方法,和原Lua decode输出完全一致 * @param {string} str 十六进制密文字符串 * @returns {string} 明文字符串 */ function decode(str) { let K = Key53; let result = ''; for (let i = 0; i < str.length; i += 2) { const cHex = str.slice(i, i + 2); const c = parseInt(cHex, 16); const L = K % POW_2_38; const H = (K - L) / POW_2_38; const M = Number(H % 128n); const m = ((c + Number((H - BigInt(M)) / 128n)) * (2 * M + 1)) % 256; result += String.fromCharCode(m & 0xff); K = L * F + H + BigInt(c) + BigInt(m & 0xff); } return result; }
内容的提问来源于stack exchange,提问作者Perhaps Maybe
相关产品推荐
相关产品推荐

