171 lines
No EOL
4.6 KiB
Lua
171 lines
No EOL
4.6 KiB
Lua
-- 游戏专用解密模块(GB2312/ANSI兼容版)
|
||
-- 适用于游戏Lua环境,精简且高效
|
||
|
||
GameCrypto = {}
|
||
|
||
-- Base64解码表
|
||
local base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
||
local base64_lookup = {}
|
||
for i = 1, 64 do
|
||
base64_lookup[base64_chars:sub(i, i)] = i - 1
|
||
end
|
||
|
||
-- 兼容的位异或运算函数
|
||
local function bit_xor(a, b)
|
||
-- 确保参数为整数且在0-255范围内
|
||
a = math.floor(a) % 256
|
||
b = math.floor(b) % 256
|
||
|
||
-- 如果有内置的位运算,优先使用
|
||
if bit and bit.bxor then
|
||
return bit.bxor(a, b)
|
||
elseif bit32 and bit32.bxor then
|
||
return bit32.bxor(a, b)
|
||
else
|
||
-- 手动实现位异或
|
||
local result = 0
|
||
local power = 1
|
||
|
||
while a > 0 or b > 0 do
|
||
local bit_a = a % 2
|
||
local bit_b = b % 2
|
||
|
||
if bit_a ~= bit_b then
|
||
result = result + power
|
||
end
|
||
|
||
a = math.floor(a / 2)
|
||
b = math.floor(b / 2)
|
||
power = power * 2
|
||
end
|
||
|
||
return result
|
||
end
|
||
end
|
||
|
||
-- Base64解码函数
|
||
local function base64_decode(data)
|
||
data = string.gsub(data, "[^A-Za-z0-9+/=]", "")
|
||
|
||
local bytes = {}
|
||
for i = 1, #data, 4 do
|
||
local c1 = data:sub(i, i)
|
||
local c2 = data:sub(i + 1, i + 1) or '='
|
||
local c3 = data:sub(i + 2, i + 2) or '='
|
||
local c4 = data:sub(i + 3, i + 3) or '='
|
||
|
||
if not (base64_lookup[c1] and base64_lookup[c2]) then break end
|
||
|
||
local chunk = base64_lookup[c1] * 262144 +
|
||
base64_lookup[c2] * 4096 +
|
||
(c3 ~= '=' and base64_lookup[c3] or 0) * 64 +
|
||
(c4 ~= '=' and base64_lookup[c4] or 0)
|
||
|
||
table.insert(bytes, math.floor(chunk / 65536) % 256)
|
||
if c3 ~= '=' then
|
||
table.insert(bytes, math.floor(chunk / 256) % 256)
|
||
end
|
||
if c4 ~= '=' then
|
||
table.insert(bytes, chunk % 256)
|
||
end
|
||
end
|
||
|
||
return bytes
|
||
end
|
||
|
||
-- 密钥扩展算法
|
||
local function expand_key(key, text_len)
|
||
local expanded = {}
|
||
local key_len = #key
|
||
|
||
for i = 1, text_len + 8 do
|
||
local pos = (i - 1) % key_len + 1
|
||
local k_byte = key:byte(pos)
|
||
local p_byte = key:byte(((i - 1) * 167 + 113) % key_len + 1)
|
||
|
||
-- 与Python完全一致的计算
|
||
local mixed = (k_byte * 131 + p_byte * 241 + i * 97 + key_len * 47) % 256
|
||
expanded[i] = mixed
|
||
end
|
||
|
||
return expanded
|
||
end
|
||
|
||
-- 解密单个字节
|
||
local function mix_decrypt(enc_byte, key_byte, position)
|
||
local original = enc_byte
|
||
-- 严格按照加密的逆序操作,使用兼容的位运算
|
||
-- 第4步逆操作:original ^ ((key_byte * 5 + position * 13) % 256)
|
||
local xor_val = (key_byte * 5 + position * 13) % 256
|
||
original = bit_xor(original, xor_val)
|
||
|
||
-- 第3步逆操作:(original - position * 11 + 256) % 256
|
||
original = (original - position * 11 + 256) % 256
|
||
|
||
-- 第2步逆操作:original ^ ((key_byte + position * 7) % 256)
|
||
xor_val = (key_byte + position * 7) % 256
|
||
original = bit_xor(original, xor_val)
|
||
|
||
-- 第1步逆操作:(original - key_byte * 3 - position * 5 + 256) % 256
|
||
original = (original - key_byte * 3 - position * 5 + 256) % 256
|
||
|
||
return original
|
||
end
|
||
|
||
-- 字节数组转字符串(通用版本)
|
||
local function bytes_to_string(bytes_list)
|
||
-- 直接将字节转换为字符串,不做特殊处理
|
||
-- 让游戏端根据自己的字符集来正确显示
|
||
local result = ""
|
||
for _, b in ipairs(bytes_list) do
|
||
if b >= 0 and b <= 255 then
|
||
result = result .. string.char(b)
|
||
end
|
||
end
|
||
return result
|
||
end
|
||
|
||
-- 主解密函数(游戏专用)
|
||
function GameCrypto.decrypt(encrypted_base64, key)
|
||
-- 参数验证
|
||
if type(encrypted_base64) ~= "string" or #encrypted_base64 == 0 then
|
||
return ""
|
||
end
|
||
if type(key) ~= "string" or #key == 0 then
|
||
return ""
|
||
end
|
||
|
||
-- Base64解码
|
||
local encrypted_bytes = base64_decode(encrypted_base64)
|
||
if not encrypted_bytes or #encrypted_bytes < 8 then
|
||
return ""
|
||
end
|
||
|
||
-- 提取数据部分(跳过前8字节前缀)
|
||
local text_bytes = {}
|
||
for i = 9, #encrypted_bytes do
|
||
text_bytes[i - 8] = encrypted_bytes[i]
|
||
end
|
||
|
||
if #text_bytes == 0 then
|
||
return ""
|
||
end
|
||
|
||
-- 扩展密钥
|
||
local expanded_key = expand_key(key, #text_bytes)
|
||
|
||
-- 解密处理(修正索引计算)
|
||
local decrypted_bytes = {}
|
||
for i = 1, #text_bytes do
|
||
local key_idx = i % #expanded_key
|
||
if key_idx == 0 then key_idx = #expanded_key end
|
||
decrypted_bytes[i] = mix_decrypt(text_bytes[i], expanded_key[key_idx], i)
|
||
end
|
||
|
||
-- 转换为字符串(通用方式)
|
||
return bytes_to_string(decrypted_bytes)
|
||
end
|
||
|
||
|
||
|
||
return GameCrypto |