关于(半)在 Flash/PHP 游戏中获得高分的建议
Posted
技术标签:
【中文标题】关于(半)在 Flash/PHP 游戏中获得高分的建议【英文标题】:Suggestions for (semi) securing high-scores in Flash/PHP game 【发布时间】:2010-09-23 03:03:28 【问题描述】:...我在这里阅读了一些讨论各种方法的主题,并且只是在寻找有关我们提出的解决方案的一些反馈。在其中一个线程中发布了一条评论,推荐了一个听起来很棒的公钥/私钥,这就是我们的想法......
客户端 - 1. 密钥存储在使用 3rd 方工具加密的 Flash swf 中。 2.高分与高分值一起散列(EX:md5('ourSecretKey' + 200)) 3. 这个值通过 AMF 发送到服务器上的 php 脚本,连同高分 (200)
服务器端 - 1. 服务器接收数据并散列传递的高分 (200) + 密钥('ourSecretKey' 存储在服务器上以及闪存中)并检查传递的散列值是否匹配它允许高分要输入,否则失败。
我知道这不是一个万无一失的解决方案,但这可以接受吗?我的意思是,对于一个简单的在线 Flash 游戏来说,这对于高分形式是否足够安全?想法?
提前谢谢你!
【问题讨论】:
【参考方案1】:对于一个可笑的短值(即:值
因此,这不是公钥私钥。它只是共享的秘密。
另外,请记住,这个共享的秘密将在您发送给用户的闪存文件中,这些天并且被简单地分解,然后您的“秘密”不再是秘密。
您需要一个具有适当加密签名的挑战-响应机制,其中从服务器为每个游戏分配一个新的签名密钥,并且不能使用相同的签名密钥提交多个分数。 (为了额外的保护;))
-
用户开始游戏。请求签名密钥。 (签名密钥是从另一个他们无法访问的密钥产生的)。
使用签名密钥对分数进行签名,然后发送
您使用发送给他们的密钥验证符号的值。
您丢弃了发送给他们的签名密钥。
但是,您仍然存在无法防止实际评分系统被篡改的问题。足够聪明的人可以对您的 SWF 对象进行逆向工程并注入新代码,将分数设置为他们选择的值。
【讨论】:
请注意,这篇文章已经发布了几年,而且事情一直在发生。 MD5 现在被认为完全损坏了。【参考方案2】:您的问题的答案是,这取决于。这主要取决于您的游戏的估计受欢迎程度。
从安全角度来看,您的解决方案与以明文形式发送高分一样安全。你在这里所做的被称为默默无闻的安全性,根据你听谁的说法,在某些情况下可能会有好处。在这种情况下,普通用户可能无法自己破解它。对于有一些 l33t h4xx 或技能的人,您不妨以明文形式发送。如果您只想阻止 Joe,那么这可能就足够了,至少在有人创建一个供 Joe 下载的假客户端之前(这取决于您的游戏的受欢迎程度可能需要几天到永远不会(或者更快,如果它是哇))。
@Kent Fredric 给出了一个更好的解决方案。然而,正如它所说,它并不能解决有人创建假客户端的问题。解决方案可能是这样的:
-
为玩家可以执行的每个操作指定一个 ID。
将玩家执行的每个操作存储在一个 id 列表中。
当游戏结束时,对分数、动作列表进行哈希处理,并使用从服务器接收到的公钥对其进行加密。 (有关详细信息,请参阅 Kent Fredric 的帖子)
将加密的哈希(通常称为数字签名)连同分数和执行的操作列表一起发送到服务器。
让服务器根据列表中的动作“玩”游戏。
验证是否获得了相同的分数。
验证数字签名是否正确。
更新服务器高分列表。
这将保证两件事:
-
分数来自正确的客户。
关于所玩游戏的分数是正确的。
但是这个方案还有一个严重的缺陷。没有办法知道游戏实际上是真的玩过的。如果客户端被入侵,该列表可能只是发送到服务器的“完美游戏”的预制件。直接篡改评分系统是不可能的,但只要付出足够的努力,某人很可能能够创建一个包含“完美游戏”的动作列表。
但是,它提供了比仅使用 Kent Fredric 帖子中的解决方案更强大的保证。要解决整个问题意味着您必须以某种方式验证客户端。这是非常困难的,因为大多数方法都很容易绕过。
最后,我只需要评论一下您选择的哈希算法:MD5 对于仍然生活在九十年代的人来说是一个很棒的哈希算法。对于我们其他人,我推荐 SHA-2 或至少 SHA-1。
【讨论】:
这个方案可以通过让服务器决定并发送每个游戏的随机种子来进一步改进。例如。客户端告诉服务器它想玩。服务器说,ok,玩种子nn发起的游戏。然后,当客户端想要上传高分时,服务器会检查高分是否实际上是游戏 nn。即使这个方案也可以被黑客入侵,但是整个游戏都需要重新启动。英。并重建。可以做到(并且已经用于一些使用这种方案的流行游戏)。 是的,当然,客户端可能仍然可以蛮力置换动作列表以找到产生理想分数的序列,但是您至少提高了生成假分数所需的计算复杂度从 O(1) 到更多的 O(n^3),必须通过蛮力排列才能找到合适的分数,至少应该让真正的业余爱好者远离,他们会转而使用机器人。【参考方案3】:如果您的游戏发行量有限,并且没有真正的金钱/赏金让玩家获胜,那么您的原始方案可能就足够了。
使用 SWF Encrypt 可能会使提取密钥变得更加困难,即使在更高级的系统中也可能是一个很好的工具。但是如果你有一个真正的公钥/私钥方案(例如 RSA),这真的是一个有争议的问题,因为公钥不是秘密,它不应该是。仍然为了防止大多数人编辑代码和篡改评分系统,SWF Encrypt 可能是一个足够好的选择。
为了让你更偏执,我还写了以下内容:
与大多数其他类似工具一样,SWF Encrypt 的问题在于它必须仍然可以在(可能已被入侵的)机器上执行脚本。因此,所有信息必须在所述机器上可用。将其与密码学的经典用法、发送消息进行比较:
当您发送加密消息时,您通常信任源和目标,因此它们都具有解密消息的密钥。你不信任的是信使,或者至少你的敌人不会拦截信使。所以快递员没有他们的钥匙,你的信息是安全的。
您的问题是,在您的情况下,您信任目的地(您)而不是来源(客户),反之亦然。由于您对快递员的信任程度更低,因此您仍然需要来源能够加密消息。因此,源需要拥有所有信息来加密和解密消息才能正常工作。您的问题是您看不到“好”来源和“坏”来源之间的区别。
我的意思是,由于代码必须仍然可以在客户端上运行,因此执行此操作的信息必须是完全可用的,尽管可能是以模糊的形式。例如,黑客可以创建自己的 ActionScript 编译器,将经过混淆的 ActionScript 代码转换为可读的内容并进行适当的更改。困难但绝对可行。
但是,如果您的分布有限且没有真正的赏金可赢,那么这种级别的复杂攻击很可能对您来说不是问题。
【讨论】:
很好地评论了来源不受信任的基本原理。【参考方案4】:块引用 最后,我只需要评论一下您选择的哈希算法:MD5 对于仍然生活在九十年代的人来说是一个很棒的哈希算法。对于我们其他人,我推荐 SHA-2 或至少 SHA-1。
呸,我知道我应该提到 SHA :)
如果我确实使用类似 swf 加密器应用程序来加密 swf 代码,这是否至少会使获取存储在 Flash 中的密钥变得更加困难?我认为如果没有那个密钥(或者至少没有很容易得到它),要弄清楚是什么被用来生成发送到服务器的哈希值将是一个巨大的痛苦。
我想到的是这样的:SWF Encrypt
再次感谢大家的这些回答,这非常有帮助。哦,这只是一个由客户发送给客户的简单 Flash 游戏,在假期打发时间的乐趣。
【讨论】:
【参考方案5】:Kent 说,我认为使用该解决方案没有任何优势。 作为客户端,我可以请求服务器端创建的密钥。好的,我不能使用它超过一次,但我不必......每次我需要一个时,我都会请求它。
-
所以我要钥匙。
创造我自己的高分
用键对高分进行散列。
将高分发送到服务器
服务器使用提交的密钥获取高分。
【讨论】:
当然,它只会增加复杂性。但是“共享秘密”是一种“发现一次,提供数百万次”的方法,而每个分数 1 个密钥至少使您依赖于分发密钥的服务器,并且它可能会限制分发这些密钥的速率键。但 Andreas 的基于序列复杂性的安全性可能会使复杂性变得难以逆转。【参考方案6】:只有一种 100% 加密分数的工作方式:记录回放。 但不仅仅是任何重播,理想情况下,您应该只记录用户按键和它们之间的空间。这样,即使有人篡改了源代码或动态的RAM,在服务器上播放的replay也会发现问题。 不幸的是,这个解决方案需要大量的工作才能成为可能。为简单起见,您只需手动验证所有分数(或最佳分数),您就会很高兴。尽管如此,您仍然必须避免一些事情:
默认随机生成器,您需要种子生成器,它始终为给定种子提供相同的随机数; 没有增量计时,抱歉; 自定义三角函数(我不是 100% 确定,我曾经听说它们可以在不同的计算机上给出略有不同的结果);可能还有更多。 然而,这种防御是牢不可破的。并且需要时间来编码:D。
【讨论】:
只制作一个他们无法下载和修改的客户端会更容易,他们必须通过像显示会话这样的远程桌面来玩整个游戏。游戏玩起来会非常慢,但你甚至不会让他们让易受攻击的代码到达他们的网络:D 但是你仍然可以 /bot/ 这样的游戏,只是一场噩梦。【参考方案7】:哇
相当困难的解决方案 8).
我曾经实现过这样的系统。虽然它不适用于所有游戏......
您应该在服务器上重玩游戏。当用户玩游戏时——您存储“状态更改”,然后以某种“重播”模式将其提供给您的游戏。
【讨论】:
以上是关于关于(半)在 Flash/PHP 游戏中获得高分的建议的主要内容,如果未能解决你的问题,请参考以下文章
使用 NSUser Defaults 保存当前游戏分数(不是高分)?