简单的问题:我开发了一个以二进制形式分发的应用程序(例如游戏)。游戏调用 home 并将用户的高分作为消息发送到在线游戏服务器。
我想做的是对消息进行数字加密和签名,这样我就可以相信它没有被篡改。
公钥加密依赖于对话的每一端都有一个秘密,但我不能依赖我的软件没有被逆向工程,并且发现了私钥。
当我知道可以对来自分布式二进制应用程序的消息进行反向工程时,是否有一种安全或足够安全的方式对来自我的分布式二进制应用程序的消息进行数字签名(在这种情况下不需要加密部分)?
简单的问题:我开发了一个以二进制形式分发的应用程序(例如游戏)。游戏调用 home 并将用户的高分作为消息发送到在线游戏服务器。
我想做的是对消息进行数字加密和签名,这样我就可以相信它没有被篡改。
公钥加密依赖于对话的每一端都有一个秘密,但我不能依赖我的软件没有被逆向工程,并且发现了私钥。
当我知道可以对来自分布式二进制应用程序的消息进行反向工程时,是否有一种安全或足够安全的方式对来自我的分布式二进制应用程序的消息进行数字签名(在这种情况下不需要加密部分)?
简而言之:不……没有万无一失的解决方案。问题在于,向您发送高分的应用程序在您在此交易中不“信任”的人的控制下运行。如果他们可以对代码进行逆向工程,那么他们就可以在签名之前更改任何消息的内容。
你就是不能。这个问题没有真正的解决方案,只是越来越多的混淆和篡改检查(恕我直言,这只是浪费时间)。假设,每个程序都可以被逆向工程、模拟和篡改。你对此无能为力。
我能想到的保证游戏结果不被篡改的唯一方法是发送某种可以重播和验证分数的游戏记录。但是,这并不能保护您的游戏不被机器人玩。这仅适用于您的游戏世界是完全确定的。
一旦您的程序的代码(无论是源代码、中间语言还是机器代码)掌握在其他人手中,他们就可以为所欲为,而您无法确定他们不会滥用它。要使滥用更加困难,请使用所有可能的方法来使逆向工程更加困难,但这并不能保证您不会滥用。
使用一些已知的算法,在我的应用程序中我使用河豚。但这并不是让它安全的原因。
游戏通常有一个过程来检查连接到服务器的程序的身份,这个过程称为“握手过程”。服务器发送一个数据包,其中包含值和一个加密的(客户端知道如何解密)blowfish 密钥。从服务器收到的河豚密钥在每次连接时都是随机的。这是握手的第一部分。
下一部分是根据连接上收到的值(随机)加密计算的整数,然后用河豚加密。
当服务器收到该数据包时,服务器会发送相同的数据包,该数据包使用新的(最终)blowfish 密钥加密。客户端必须通过使用旧的河豚密钥解密来找出该密钥,然后使用收到的值进行计算从第一个数据包开始。
这是握手过程,完成后,您可以在同一主体上发送您的分数(或者可能将其放在握手中并在握手完成后发送一个假数据包以欺骗反向者)。
做的太多了,但对于逆向者来说也太多了。
解决问题的另一种方法是根据数据包内容通过您自己的计算添加一个两字节(字)安全值(CRC)。服务器将检查该值以及它是否无效 -> 断开连接。
好问题!这里很多人已经说过了——你最终需要在你的应用程序中构建一个密钥,这可能可以通过逆向工程来检索。
阅读可信计算。这是围绕内置在您的 PC 中的公钥/私钥构建的 - 您的 PC 永远不会允许您访问。内存窗帘/密封存储将使攻击者难以尝试发现传递给您的应用程序的密钥。
不,一般不会。您面临其他评论中提到的问题。
问题变成了成本之一。破解保护系统的成本是否高于其保护的价值?从成功闯入中恢复的成本是多少?
由于高分表通常不是高价值目标,您可能想尝试以下任何一种:
随着高分,发送一些关于游戏状态的信息;游戏时间、等级、收集的奖金等。加密/混淆这些数据。这将帮助服务器确定高分在理论上是否有效。忽略任何明显是假的高分。
使用共享密钥加密发送高分。不要将共享密钥作为纯文本存储在您的应用中。最好使用算法实时计算。
混淆您的客户端代码。
使用客户端 IP 地址和时间戳存储高分。
不可以。客户端软件要对其进行数字签名,它必须具有私钥。如果软件有私钥,用户可以发现(并可能滥用)它。