Read this manual in English

应用加密

应用加密是一个很大的主题, 内容包括从安全开发实践到应用上线后的数据保护. 本教程涵盖了安全与加密的部分内容, 讨论在使用 Defold 引擎, 工具和服务时与安全加密相关的技术:

  • 知识产权保护
  • 反作弊解决方案
  • 网络通信安全
  • 使用第三方软件
  • 使用云编译服务器
  • 可下载资源

保护您的知识产权免遭盗窃

大多数开发人员关心的问题是如何保护他们的作品不被盗. 从法律的角度来看, 版权, 专利和商标有助于保护视频游戏知识产权的方方面面. 版权赋予开发者发表创意作品的专项权力, 专利保护创造发明, 商标保护名字, 符号和标志.

为了保护游戏凝聚的创意和劳动, 技术手段也是有必要的. 要知道您的游戏一旦上市, 就无法阻止玩家想方设法提取游戏资源. 针对游戏文件的反向工程和各种动态提取工具都能搞到游戏资源, 因为无论如何, 贴图, 模型以及各种资源最终都要解压发送给 GPU 或者载入内存的.

出于这个原因, 我们的看法是, 不怕贼偷, 就怕贼惦记.

开发者可以提升游戏资源窃取的难度, 但永远不是不可能. 这通常包括用各种手段加密, 混淆以达到保护和隐藏游戏资源的目的.

源代码混淆

应用源代码混淆是一个故意降低代码可读性, 而不影响游戏输出的自动化过程. 目的不仅是为了防止被盗, 还能提高作弊的难度.

可以在 Defold 编辑器里进行代码混淆, 这一步要么作为预编译步骤要么整合成为 Defold 编译工作中的一部分. 预编译混淆就是在 Defold 编译开始之前用某个工具给代码进行混淆操作.

编译工作中混淆就是使用 Lua 编译插件把代码混淆作为编译工作的一部分. Lua 编译插件可以输入原始代码, 输出混淆后的代码. 具体示例可以参考 Prometheus 扩展, 它基于 GitHub 上的 Prometheus Lua 混淆器. 下面展示了使用 Prometheus 主动混淆一小段代码的例子 (注意这种高强度混淆会对 Lua 代码的运行效率产生影响):

示例:

function init(self)
 print("hello")
 test.greet("Bob")
end

混淆后输出:

local v={"+qdW","ZK0tEKf=";"XP/IX3+="}for o,J in ipairs({{1;3};{1,1},{2,3}})do while J[1]<J[2]do v[J[1]],v[J[2]],J[1],J[2]=v[J[2]],v[J[1]],J[1]+1,J[2]-1 end end local function J(o)return v[o+45816]end do local o={["/"]=9;["8"]=48;["9"]=1;q=38,o=62;V=33;y=43,d=61,B=50,L=54;v=2;["0"]=21,n=31;p=63;R=5;N=3;i=10;e=35;C=7;l=56;a=47,J=58;m=59;["2"]=36;z=11;M=12;Z=26;O=18;["5"]=20;s=8,["4"]=30,P=55;w=4;U=29;Q=28;r=24,h=41;G=45;c=19;W=34,k=57;T=14,t=44,S=0;f=60;F=42,E=27;u=40;X=25,j=17;["3"]=23,b=13;["1"]=53;Y=32,A=22,K=6,["+"]=16,["6"]=46;["7"]=51;I=37;D=52;H=15,x=49,g=39}local J=type local x=string.sub local d=v local l=string.len local W=string.char local L=table.insert local w=table.concat local h=math.floor for v=1,#d,1 do local X=d[v]if J(X)=="string"then local J=l(X)local H={}local S=1 local k=0 local K=0 while S<=J do local v=x(X,S,S)local d=o[v]if d then k=k+d*64^(3-K)K=K+1 if K==4 then K=0 local o=h(k/65536)local v=h((k%65536)/256)local J=k%256 L(H,W(o,v,J))k=0 end elseif v=="="then L(H,W(h(k/65536)))if S>=J or x(X,S+1,S+1)~="="then L(H,W(h((k%65536)/256)))end break end S=S+1 end d[v]=w(H)end end end local function o(o)test[J(-45815)](o)end function init(v)print(J(-45813))o(J(-45814))end

资源加密

在 Defold 编译过程中, 游戏资源会被处理为 Defold 引擎理解的格式. 贴图被编译成为 Basis Universal 格式, 碰撞器, 游戏对象和组件从原始可读文本被转化成为相应的二进制格式, Lua 源代码被编译为字节码. 其他资源比如音效则保持不变.

处理完成后游戏资源会被一个一个地打入游戏包. 游戏包是个大号二进制文件, 其中每个资源的位置被存储在一个包索引文件中. 格式文档参见 这里.

Lua 代码被打包前可以指定是否进行加密. Defold 提供了一种简单的分组加密算法用于保护代码中的字符串不至于被一些二进制预览工具打开就能看到. 这也不是很安全因为 Defold 已在 GitHub 上开源, 包括加密密钥.

允许通过实现一个资源加密插件来对 Lua 源代码实施自定义加密手段. 资源加密插件由两部分组成, 一个编译时对资源进行加密的部分和一个运行时对资源进行解密的部分. 作为基本应用的开端, 有一个简单的资源加密插件实现 在 GitHub 上.

游戏防作弊

游戏产业的历史就是作弊产业的历史. 以前作弊码常常被印刷在著名游戏杂志里, 有些外挂在早期家用电脑时代已经开始售卖. 随着游戏产业的进化, 作弊器和手段也在不断进化. 目前流行的作弊机制包括:

  • 注入作弊代码重新打包游戏
  • 能让游戏更快或更慢执行的速度齿轮外挂
  • 通过屏幕可视化分析实现的自动瞄准或自动行动机器人
  • 实时代码注入和内存数值修改以增加分数, 子弹数, 命数等等

防止作弊很难, 难到接近不可能. 即使是云游戏, 那种运行在远程云服务器上, 然后把输出串流到用户设备上的游戏, 都不能完全杜绝作弊.

Defold 不提供任何引擎内置反作弊方案或者工具, 而是把这些工作外包给专门做游戏反作弊技术的公司.

网络通信安全

Defold 套接字和 HTTP 通信支持使用安全套接字连接. 在客户端与服务器的双向通讯中, 推荐全部使用安全套接字连接以进行身份验证并保证任何交换数据的隐私和完整. Defold 使用流行并被广泛使用的 Mbed TLS 作为 TLS 和 SSL 协议的实现. Mbed TLS 由 ARM 及其伙伴科技公司所开发.

SSL 证书验证

为防止黑客在您的网络交流中实施中间人攻击, 可以在与服务器进行连接时的 SSL 握手期间验证证书链. 通过 Defold 向网络客户端提供公钥列表即可. 关于网络通信安全的更多信息请参阅 网络教程 的 SSL 验证章节.

第三方软件使用安全

虽然不用第三方库或者原生扩展也能做游戏, 但是从我们的官方 资源大厅 获取资源提升开发效率已成为开发者的共识. 资源大厅里有超多资源, 从第三方 SDK 整合包, 到屏幕管理, UI 库, 摄像机控制等等等等.

资源大厅里的资源未经 Defold 基金会审核, Defold 基金会不为使用它们造成的计算机系统损坏或设备损坏或数据丢失等任何后果负责. 详见我们的 条款与条件.

我们建议您在使用这些资源之前仔细审核, 确认资源适用于您的项目之后马上把它拷贝一份出来, 以保证它不会受到未来更新造成的未经审核的改变.

云编译服务器的使用安全

Defold 云编译服务器 (同时也是扩展编译服务器) 用于帮助开发者为游戏增加功能而不用重新编译 Defold 引擎. 当包含原生代码的 Defold 项目被第一次编译时, 所有相关资源都会被上传到云编译服务器用来编译一个自定义版本的 Defold 引擎然后回传给开发者. 类似流程也会发生于当项目使用自定义 application manifest 剔除了不必要的引擎组件时.

云编译服务器被托关于 AWS 并且尽最大可能做好了安全工作. 然而 Defold 基金并不承诺云编译服务器完全满足您的需求, 没有缺陷, 没有病毒, 没有错误, 绝对安全或者永远在线, 使用安全. 详见我们的 条款与条件.

如果安全性和可用性对您来说非常重要, 我们建议您自己架设私有编译服务器. 假设私有编译服务器的方法详见 GitHub 上扩展仓库的 主 readme 文件.

可下载资源的安全

Defold 的热更新系统允许开发者把主游戏包的部分内容划分出来以便随用随下. 典型的用例就是随着玩家游戏进程的推进, 按需下载关卡, 地图或者游戏世界.

这些被划分出来的更新包被下载好准备用于游戏的时候, 引擎会对它们进行加密验证已确定它们没有被篡改. 该验证包括多项检查:

  • 二进制格式是否正确?
  • 当前运行的引擎版本是否支持下载的内容?
  • 下载的内容是否使用了正确的公私钥进行签名?
  • 下载的内容是否完整且没有遗漏任何文件?

该过程的详细步骤请参考 热更新教程.