2

我有一个客户端-服务器游戏,客户端连接到服务器并在游戏期间保持连接(大约 5-60 分钟)。

我希望新客户能够安全地注册,并允许现有客户进行身份验证,而不必担心登录凭据被暴露。

问题是,出于性能原因,最好在游戏会话中坚持使用简单且廉价的加密,如 RC4,但对称密钥并不容易确保注册过程的安全。

由于无论如何我都想保留一个单独的登录服务器,所以我的想法是这样的:

  1. 客户端使用凭据(或注册信息)向登录服务器发送 HTTPS 请求
  2. 登录服务器收集用户信息,并生成临时 RC4 会话加密密钥
  3. 用户信息 + RC4 会话 + 时间戳 + 摘要(我可以依靠两个服务器在时间上同步)与秘密对称密钥,在游戏服务器和登录服务器之间共享。
  4. 打包后的数据 + RC4 会话加密密钥 + 游戏服务器的 ip 地址作为对 HTTPS 请求的回复发送给客户端。
  5. 客户端打开与游戏服务器的连接,发送初始未加密的 hello 消息,并将加密的用户信息作为有效负载。
  6. 游戏服务器解包(3)中打包的数据。它现在知道用户和它应该使用的 RC4 加密密钥。
  7. 如果时间戳指示登录凭据已过期,则会向客户端返回错误(然后客户端将检索新信息)。如果无法使用摘要验证解密的用户数据,则会返回不同的错误。
  8. 如果一切正常,服务器会发送一个未加密的 LOGIN_OK,然后开始 RC4 加密通信。

可能的安全问题:

  • 游戏服务器 100% 信任它解密的用户信息。这使得服务器完全解耦,这很好,但如果密钥被泄露,用户可以完全伪造他们的用户信息。这可以通过轮换这些键得到一定程度的缓解,这样每天或每个月都有一个新的键。游戏和登录服务器都可以从管理其密钥的第三个服务器获取此信息。这可能是矫枉过正,因为:a)如果在服务器上暴露源代码的闯入情况下,可以使用新密钥重新启动它们 b)足够好的密钥+加密应该使蛮力攻击变得困难(关于算法的建议?)

  • RC4 不是最安全的算法,但我确保丢弃前 512 个字节左右,并且每个密钥仅在有限的时间内有效,例如 24 小时。

  • 从我所见,似乎不受中间人的影响:SSL 保护 RC4 会话密钥,在 (5) 中,发送到游戏服务器的 RC4 会话密钥也被加密。唯一可能的是 DoS 并导致用户再次请求密钥。如果(2)中的数据被缓存到过期,这不应该创建一个新的数据包。

  • (3)中的加密可以通过向密钥添加随机位来改进。这些随机位与加密数据包一起发送,并在(5)中呈现给游戏服务器。在 (6) 中,游戏服务器将这些随机位添加到他的密钥中,并使用结果来解密数据。这样,攻击者就无法看到打包数据何时发生变化。

我在这里忽略了任何漏洞吗?

创建的有效负载摘要:

  • 客户端登录凭据(受 SSL 保护),发送到登录服务器
  • 用户信息 + 时间戳 + 临时游戏服务器会话密钥 + 由登录服务器使用与游戏服务器共享的密钥加密的摘要,提供给客户端 - 无需修改它 - 将其传递给游戏服务器。应该是耐回火的,因为:a)客户端不知道密钥 b)具有时间戳以避免重新发送相同的数据 c)用于验证内容是否正确加密的摘要
  • 登录服务器向客户端发送的临时游戏服务器会话密钥以及加密的有效负载。受 SSL 保护。
  • 客户端游戏服务器登录包,由登录服务器接收到的加密包组成。

加密密钥摘要:

  • 临时游戏服务器会话密钥:由登录服务器随机生成,用于加密游戏服务器<->客户端通信。由登录服务器生成,提供给客户端和游戏服务器。
  • 秘密用户信息加密密钥。在游戏服务器和登录服务器之间共享,用于将用户信息传递给游戏服务器,客户端作为信使。客户端不拥有此密钥。
4

5 回答 5

2

听起来您正在尝试重新发明 SSL。为什么不向每个客户端颁发证书(由您自己的根权限签名),并让他们通过 SSL 连接到游戏服务器,并进行相互身份验证?

于 2011-02-17T03:26:25.523 回答
2

首先,我不会使用 RC4。周围有更快和更安全的流密码,所以如果你同时控制客户端和服务器,那么你可能会比 RC4 做得更好。对于 Fluhrer、Mantin 和 Shamir 攻击,仅丢弃 512 个字节可能还不够,但即使您丢弃更多字节,还有 Klein 的攻击等。我不知道是否值得麻烦。

其次,确保您生成的密钥是随机的。我知道这似乎很明显,但例如参见: http: //www.debian.org/security/2008/dsa-1571

但真正的问题是这部分:“游戏服务器 100% 信任它解密的用户信息。这使得服务器完全解耦,这很好,但如果密钥被泄露,用户可以完全伪造他们的用户信息。”

您必须假设用户知道密钥。他的游戏客户端必须知道密钥才能与服务器通信。如果用户可以使用他的真实数据通过 ssl 登录,获取流密码的密钥,然后将他想要的任何信息发送到游戏服务器,那么攻击者所要做的就是获取一个帐户并为所欲为。

更改密钥的频率无关紧要,因为每次更改时您仍必须将其提供给客户端,因此您不妨在每个字节后更改它,这仍然无关紧要。

这比使用的密码或密钥生成更重要,因为如果他只是得到它,没有人会暴力破解密钥。

你永远不应该相信客户。您应该将客户端数据存储在服务器端并将其与密钥匹配或签署数据并验证它或使用 HMAC 等,因为如果游戏服务器 100% 信任用户信息,那么您迟早会遇到问题。几乎没有办法解决它。

于 2011-02-16T12:45:22.467 回答
1

我了解您不能在游戏服务器和客户端之间使用 SSL,因为您不想再次握手。

乍一看,该协议似乎没问题。也没有重放攻击,因为您确实需要对称会话密钥来做任何有意义的事情。您可以做的最好的事情是切换到 AES 也非常快速且非常安全。我非常怀疑切换到 AES 会影响性能。

此外,您提到的第一个安全问题要点也不是真正的问题。好吧,这是桌面上所有客户端的一个问题,例如,您的浏览器在通过 HTTPS 通信时遇到了同样的问题。所以你真的不必解决它。如果您想主动监控操纵尝试,您的游戏逻辑必须以某种方式寻找不良行为。您无法通过重新键入来解决它。

于 2011-02-17T20:23:41.190 回答
1

最后我还在 sci.crypt 上发帖,我将尝试总结下面的建议更改(据我所知),以防它可能感兴趣。

第 1 步:客户端使用凭据向登录服务器发送 HTTPS 请求

假设凭证采用登录令牌的形式,还要添加一个自分配的唯一 ID。

第三步:用户信息+RC4会话+时间戳+摘要

使用确保完整性的加密算法,而不是显式使用摘要。例如 AES-GCM 或 AES-CCM。在步骤 1 中添加额外的 id 字段。将 ip 也添加到游戏服务器。

第四步:将打包后的数据+RC4会话加密密钥+ip地址作为回复发送给游戏服务器。

将时间戳提供给客户端将允许客户端知道会话何时过期。这避免了使用过期凭据不必要地连接到游戏服务器。

第 5 步:客户端打开与游戏服务器的连接,发送初始未加密的 hello 消息,其中包含加密的用户信息作为有效负载。

将步骤 1 中未加密的自分配 id 添加到有效负载中。

第六步:游戏服务器解包(3)中打包的数据。它现在知道用户和它应该使用的 RC4 加密密钥。

游戏服务器既将自己的 ip 与加密的 ip 匹配,又将加密的 id 与客户端提供的 id 匹配。第一个防止用户使用相同的凭据访问不同的服务器。

第八步:如果一切正常,服务器发送一个未加密的LOGIN_OK,RC4加密通信开始。

此时游戏服务器无法确定客户端的身份。使用会话密钥并使用 AES-GCM/CCM 加密 nonce + 严格增加会话 id + 登录成功状态并将其发送给客户端。

客户端解密并检查登录成功状态。如果这是真的,那么客户端就知道游戏服务器知道会话密钥(GCM/CCM 验证数据包没有被篡改)。客户端返回 sid + nonce。

服务器验证 sid + nonce 与发送的值相同。

最后,客户端和服务器通过使用 sid + nonce + salt 对会话密钥进行哈希处理来创建新的会话密钥,从而为后续通信创建密钥,以防止可能的重放攻击。

关于 RC4

RC4 中存在漏洞,但由于相当激进的密钥重新调度,因此该方案可能就足够了。但是,有一些更安全、更快的现代密码,例如 Snow 2.0 或 Trivium。

于 2011-02-25T11:54:19.783 回答
0

只需使用 SSL 连接到游戏服务器。现代密码分析已经导致一些更好的加密算法的一些非常快速的实现。例如,经过优化的 AES 实现可以轻松地在任何远程现代机器上以超过 150MB/s 的速度进行加密。此外,虽然 AES 受到高度重视,但我知道它确实有两个弱点,但如果使用得当,这些弱点就会变得微不足道。

我注意到您没有提到您将在客户端和游戏服务器之间使用高级密钥调度算法。不这样做会使加密算法的弱点更加严重。SSL/TLS 应该为您安排密钥。

于 2011-02-17T06:11:15.637 回答