这方面的东西在网上找了一下,发现资料居然很少,几乎没人提出实质性的内容。最近我做的游戏开始做这部分工作了,自己以前也没开发过这样的东西,只好简单分析了一下别人的系统,在按自己的理解设计了一个方案。我想这部分知识或许对不少人能有帮助,所以把这个方案设计就公开了。其实连公开都不行的方案估计也没安全性可言。
考虑到每个人的基础不一样,所以开篇两节详细介绍了下基础概念。其实我没做过类似的系统开发,如果有说的不对或设计不好的地方也请不吝指教!
1. 设计目的
网游的安全性我个人认为主要分两块:一个是客户端的安全,就是防止反编译串改客户端;另外一个就是网络通讯安全,防止别人在网络层截获数据包并串改。
前者最常用的办法就是混淆编译代码、加壳之类的,我前面一面blog就是说androird端的混淆,但这些工作感觉是不可能杜绝破解的。所以进一步加强的手段就是让数据都是从服务器出来,客户端提交的数据认为都是不可靠的,这样客户端串改计算就不行了。另外一个就是会做辅助外挂,这会让你游戏本身设计的操作性变得和预想不一样了,这个我建议还是学学WOW和梦幻西游,直接把大脚集成了或者直接内置辅助功能但稍作限制,比如辅助功能开启一次维持5分钟之类的。
本文重点说的是后者,网络层情况非常复杂,有可能是在你本地电脑上的木马,也可能是别人串改过的路由器,也可能是局域网的其他机器等等,只要能拿到你网络层数据包的都可以做这些事情。这里最直接的办法就是让通讯的数据加密,没有密钥你拿到也看不到明文。
2. 基础概念
看过密码学的都知道,其实目前真正可靠的加密算法无非就那么几种,基本都是根据每个加密的需要就直接选定算法了。
单向hash算法:md5,sha1,这类算法就是让你的原文能稳定hash成一串密文(每次hash结果是一样的),且密文的冲突较小(重复结果少)。常用于原文比对和密码保存上。
有加密就有破解,网上大量的md5破解工具是怎么回事呢,因为算法本身的不可逆性就决定只能用暴力破解,也就说记录一堆原文对应的密文,然后反向查找,所以你原文足够诡异,暴击破解也非常困难。(小插曲:山东大学的一个教授做出了一个能较为快速查找md5碰撞的算法,就是能找出两个不一样的原文对应一个密文,但找到的另外一个明文基本是完全无意义的,所以这个完全不影响到实际使用的安全性)
对称加密算法:DES,3DES,这类算法就是用同样的密钥加密和解密,特点就是效率非常高。3DES其实就是加密了3次的DES算法,原因是计算机发展太快,运算速度越来越快,导致DES的密钥能比较快计算出来,但3DES好像是几十年才能算出来。这个常用于大数据或长时间通讯加密。
非对称加密算法:RSA,DSA,这类算法最大的特点就是密钥对,一个密钥加密的数据,只有另外一个密钥可以解密,所以生成后一个拿来做自己的私钥不告诉别人,一个拿来做公钥给其他人。这个算法效率较低,但其特性在很多场合非常有用,比如linux的ssh登录验证。
3. 加密通讯设计思想
基于以上的概念,基本原则就是实际正常通讯肯定要走3DES,但由于3DES的对称性所以要动态获取,获取的方式必须是更安全的办法,所以可以考虑客户端保存一个公钥去和服务器通讯拿3DES的密钥。这里有个前提,就是认为服务器端是绝对安全的,但如果考虑内部人员破解,那就要想其他办法了,我觉得人员范围缩小到这个地步,就可以直接用行政手段了。
此外,考虑到3DES加密后为byte[],这样的数据作为字符串传递会很长,所以很有必要用Base64进行一次压缩再传递,我测试了一下,可以压缩到到原大小的1/4。
4. 通讯的时序图
5. 更复杂的加密方法
我本来想再加点东西上去,但是考虑到说的太多细节反而会掩盖重要部分,所以这里简单追述一下。以上只是最基本的通讯过程,想更安全的话,还能再做点文章。以下我只是抛砖引玉,提出几个方案,希望有朋友能给出更多更好的方案。
1) 对密钥再加一些salt,就是发过去的密钥并不是最终密钥,C/S双方再根据约定逻辑修改密钥才是最终的。
2) 客户端每次都要传送uid也不安全,可以再生成一个access code作为身份验证,这个想法比较类似Oauth。
3) 登录密码用md5或者sha1转换一次。
4) 弄一个自定义的加密或密钥进行二次加固,并经常更换
5) 走网络层以外的方式获取密钥,比如短信、类似BB机的key
6) 服务器返回密钥用私钥加密不安全,可以考虑由客户端请求是生成一个随机密钥,用公钥加密发给服务器端做一次通讯。
本文转自passover 51CTO博客,原文链接:http://blog.51cto.com/passover/899225,如需转载请自行联系原作者