bayuMIR/Mirserver/Mir200/Envir/QuestDiary/系统类/字符串加解密 - 复制.lua
2026-06-12 00:25:44 +08:00

171 lines
No EOL
4.6 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 游戏专用解密模块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