全篇以目前主流的 sha-256 哈希算法举例

哈希算法是什么?

哈希算法能够将一个字符串(原始数据)转换为另一个字符串(哈希值),举例:

有什么特点?

  1. 固定结果

  2. 单向性

  3. 固定长度输出

  4. 雪崩效应

  5. 计算快

哈希碰撞是什么?

根据抽屉原理,不同原始数据可能会产生相同的哈希值。但这个概率极极极极极极低,sha-256 算法还没有公开发现有碰撞的例子,无需担心(其它哈希算法已发现碰撞,如 md5 ,可以去网上搜搜)

如何使用&使用场景

我想在模组中写一个VIP名单,但我不希望别人能通过直接看代码的方式来让别人知道VIP具体有谁,那么就可以使用哈希算法

local vips = {
	-- 提前写一份转为哈希值的id表
	["cb9e7e5c0574707a74488f74a2342e78d3303f5544fb992bb687a6a652cecddf"] = true, -- KU_1234ABCD
	["c358271c721e7ba76f30818b75ffd3177d0670955c48217a0bd78ecb5ed7cc8a"] = true, -- KU_AABBCCDD
}

local sha256 = reuiqre("utils/sha-256")
AddPlayerPostInit(function(inst)
    if inst then
        inst:DoTaskInTime(3, function()
            if inst and inst.userid then
                -- 将玩家的id转为哈希值,寻找vip列表中是否有同样的哈希值
                local is_vip_user = vips[sha256(inst.userid)]
                if is_vip_user then
                    -- 这是vip用户,对他做些什么
                end
            end
        end)
    end
end)

我想试试

sha-256在线工具

lua sha-256库下载(不要直接使用lua文件,如果明文代码的库被篡改那么会直接绕过列表,建议进行混淆处理)

穷举攻击

攻击者现在拿到了vip名单,虽然无法直接还原id

但可以通过暴力破解(通常需要几天~几十天时间)的方式,一个个算出所有id的哈希值,并进行匹配,从而拿到id

其他建议

  1. 对vip列表加随机后缀,尽管依然可以使用穷举攻击破开,但也增加了几倍时间成本。并且代码更新变动一次,攻击者就得重新算一遍
  2. 加一些假的id,混淆视听
local vips = {
    -- 在原先的基础上加了一个字母后缀 每次更新就变一次
    ["84fd352eeedf0d59a3c6f9eb270161d5cc6b90ee8ba2c2bdf1a6ccfab5fc675e"] = true, -- KU_1234ABCD_x
    ["6d39128d8af33ebd47dced977df1533b284f8c1be0bb9ebed03186fb2076e065"] = true, -- KU_AABBCCDD_u
    -- 加一些假的vip 永远也算不出id
    ["3b45470f2c72bb94a028c11d6c200db5b0f07323c173383d10d90834a4fb14ea"] = true, -- 11112222ccccdddd
    ["6df54fa409dc5920d72b68effa3103818c05c4424c9556df7bf2b2f5e9fe3ab0"] = true, -- kkkkZZZZppppuuuu
}

local sha256 = require("utils/sha-256")

local chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" -- 字符后缀每次更新就变一次
local function IsVipUser(userid)
    -- 遍历所有字符进行拼接 挨个算一遍
    -- 也可以多加几位后缀 但性能会暴涨
    for i = 1, #chars do
        local char = chars:sub(i, i)
        local hash = sha256(userid .. "_" .. char)
        if vips[hash] then
            return true
        end
    end
end

AddPlayerPostInit(function(inst)
    if inst then
        inst:DoTaskInTime(3, function()
            if inst and inst.userid then
                if IsVipUser(inst.userid) then
                    -- 这是vip用户,对他做些什么
                end
            end
        end)
    end
end)