明文协议的包被抓包重放、被中间人篡改的故事在上一代游戏里层出不穷。消息加密层给会话加一层密钥协商:每次登录派生独立密钥,载荷全程加密,抓包者看到的是一串无效字节。
---握手:双方随机数派生会话密钥
function Crypto.handshake(actor, clientNonce)
local serverNonce = Crypto.randomBytes(16)
-- 双随机数加预置种子派生 128 位会话密钥
actor.sessionKey = Crypto.derive(
clientNonce, serverNonce, PRESEED)
actor.keyAt = os.time()
-- 服务器随机数回传,客户端可派生同一密钥
return serverNonce
end
---载荷的加解密
function Crypto.seal(actor, body)
local iv = Crypto.randomBytes(8)
return iv .. Cipher.crypt(body, actor.sessionKey, iv)
end
function Crypto.open(actor, pkt)
local iv = pkt:sub(1, 8)
return Cipher.crypt(pkt:sub(9), actor.sessionKey, iv)
end
握手交换双方的随机数,客户端随机数随登录请求上行,服务器随机数随握手响应下行,双随机数加预置种子派生出 128 位的会话密钥——双方各自算出同一把钥匙,密钥本身不在网络上传输。每个会话的密钥独立,抓到一个会话的密钥推不出另一个会话的。载荷加密用会话密钥加随机 IV,同样的内容每次密文不同,重放与比对分析的难度双双抬升。
---密钥的定时轮换:30 分钟一换
setontimerex(78, 1800)
function Crypto.rotate()
for _, actor in pairs(Online.all()) do
if os.time() - actor.keyAt > 1800 then
actor.oldKey = actor.sessionKey
actor.sessionKey = Crypto.derive(
actor.sessionKey, Crypto.randomBytes(16))
actor.keyAt = os.time()
actor.keyPhase = "switching"
end
end
end
---切换期的双密钥解密
function Crypto.openSmart(actor, pkt)
local body = Crypto.open(actor, pkt)
if not body and actor.oldKey then
actor.sessionKey = actor.oldKey
body = Crypto.open(actor, pkt)
actor.sessionKey = Crypto.currentKey(actor)
end
return body
end
密钥 30 分钟轮换一次,轮换的派生用旧密钥加新随机数——旧密钥的暴露不危及轮换后的安全。切换期的双密钥解密兜住在途的包:轮换瞬间客户端还拿旧密钥加密的包用旧钥解开,新包走新钥,切换对玩家零感知。加密的性能账要算清:批量包(移动、飘字)的加密开销在千分之几毫秒级,千人同屏的总量可控;解密失败进静默计数,连续失败即协议异常处理。加密层与签名的分工:加密管保密、签名管完整,两层各司其职不互相替代。
加密的互通测试:新旧客户端与多版本服务器的握手矩阵全绿;解密失败的计数监控,失败率的突增提示密钥状态失步。
随机数曾经用固定种子,两台服务器的会话密钥相同,种子接入引擎的熵源。轮换曾经没有双密钥期,切换瞬间的在途包解密失败被当攻击踢线,切换期的兜底解密修复。IV 曾经复用,相同内容的密文相同让频度分析有机可乘,IV 每包随机。
加密对全部写操作协议强制,读协议的明文容忍按数据敏感度评估。密钥的轮换周期与算法参数进配置,算法的升级预留版本号字段。握手失败的处置与风控联动,握手异常的客户端版本进观察名单。
本文由 996 技术组基于 996 引擎官方知识库与浮生梦老师课程体系整理。团队长期从事传奇类引擎 Lua 后端逻辑、客户端界面与商业版本交付,内容以官方知识库与真实项目为出处,按版本持续修订。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
实战应用:用在哪里 沙巴克占领行会坐收税收却只进不出,非占领行会的玩家心里不平衡。税务官玩法把税收做成明账:占领行会对摆摊与…
实战应用:用在哪里 高端玩家婚姻系统只有仪式没有过程,社交绑定缺一个高光事件。比武招亲做成擂台玩法:擂主设擂摆彩头,攻擂者报…
实战应用:用在哪里 开服七日限时礼包发到第六天断了粮,9 月 1 日当天领奖按钮灰的,投诉当天破千。事故根因是一条数字日期循…
实战应用:用在哪里 玩家拔线不退游戏,连接半开着,人不在指令也没有,在线数虚高,容量预案被假数据带着跑。心跳探测给每个在线玩…
实战应用:用在哪里 周三发了合成系统补丁,周四又改强化概率,两条变更叠加后玩家分不清是哪个改出来的。发布日历把全月变更集中排…
实战应用:用在哪里 容量预案需要知道滚动一小时的副本进入峰值,而不是全天累计。滑动窗口用 60 个槽位每槽记一分钟的进入数,…