Java加密日志

3
我正在制作一款游戏。我已内部构建了日志记录设施,并提供了诸如“常规、日志、异常、发送、接收、调试”等消息类型。
发送和接收日志包含原始的日志信息,因此它们真正包含我在网络上发送的内容。
游戏使用客户端-服务器模型,并使用SSL连接,以使网络信息无法被更改。但是为了记录日志,我将以纯文本形式记录文本,这显然会引起问题。此外,我计划仅掩盖(使用*)任何个人信息(例如密码等)。
然而,我有几个顾虑:
- 客户端程序包含用于SSL的信任存储区,并且服务器的主机名/IP和端口也不是秘密。因此,如果一个人知道该发送什么到网络上,那么他可以像客户端一样操作,对吗? - 如果一个人能够看到客户端发送和接收的内容,那么他可能很容易制作一个机器人。(这个游戏是一个基于回合的2D游戏,所以通过简单地依赖所有网络数据,你应该能够玩这个游戏。在任何情况下都不需要鼠标的技巧。) - 总的来说:我如何记录所有信息并将其写入文件,但没有其他人能够阅读、修改或以任何方式使用它?
非常感谢您的所有意见,我也希望能得到如何实现这样一个系统的具体建议。
敬礼。
3个回答

7
如果您担心服务器数据加密问题,最简单的解决方案是使用Truecrypt这样的全盘加密程序 - 这将保护服务器数据,即使有人偷走了机器/硬盘。
如果你在客户端加密数据,那么这意味着加密密钥也必须在客户端的某个地方(即使它在主存储器中)。可以加密或混淆日志信息以使用户更难读取,但要注意,如果用户付出足够的努力,仍然可以读取它。因此,混淆数据的最佳方法是使用从未保存到磁盘的密钥进行加密 - 例如,当用户登录时,发送一个新的加密密钥给他们的客户端应用程序用于加密日志数据;在服务器上,记录您发送给客户端的密钥和UTC时间戳。使用未加密的时间戳存储日志,以便当用户的客户端应用程序发送日志数据时,您将知道要使用哪个密钥来解密它。显然,用户可以轻松更改时间戳,但这相当于用户仅从其机器上删除日志数据(您无法防止);同时,用户很难弄清楚使用了什么密钥来加密数据,因此用户不容易读取或伪造日志数据(但是,如果用户付出足够的努力,仍然可以读取/伪造日志数据)。
您可以采取措施来混淆内存中的加密密钥,例如将其存储在多个部分中。例如,假设您正在使用AES 128,则可以将密钥存储在两个64位块中,然后在加密数据之前将它们连接起来,完成后立即从内存中擦除连接的密钥。或者您可以存储两个128位密钥进行XOR运算,同样在完成后从内存中擦除XOR密钥。虽然专业用户仍然可以找到密钥,但这会使他们更加困难。
另一个步骤是使用除AES以外的加密算法,例如Twofish或Serpent等其他AES决赛选手(不要实现自己的加密算法,您最好公布您正在使用强大的算法,如AES,而不是使用一个弱的混淆算法)。只需记住混淆加密库的类和方法名称,以使用户更难确定您正在使用哪种加密算法。(如果您编译为机器代码,则这样做效果更好 - 如果您使用Java,则可能不值得,因为用户可以简单地反编译您的代码并使用您自己的解密代码解密日志文件。)

在确定玩家是人还是机器人方面,即使比你更有预算的游戏也不能可靠地做到这一点 - 你真正能做的就是将用户踢出或者在他们展示“机器人”的行为时发送某种验证码,但这并非万无一失,你确实应该优先考虑不惹恼合法用户而不是踢出机器人。


请注意,Java中的现代垃圾收集意味着您无法可靠地“从内存中擦除”任何内容。甚至清零数组也不意味着内存管理器没有在其他地方创建了一个短暂的副本。 - Jazzepi

2

你没有太多可以做的。如果客户端是用Java编写的,那么反向工程或使用类似AspectJ的工具来监视客户端写入网络的内容就非常容易了。同样地,对于任何写入日志系统的数据,即使最终加密,也可以被读取。


那么,即使没有登录,任何人都可以像真正的客户端一样操作吗? SSL 的一个目标不是让所有网络数据都得到保护吗?有没有办法确定我正在处理真正的玩家还是机器人? - skiwi
SSL保护客户端和服务器之间发送的数据免受拦截。但它不能阻止客户端检查数据。 - Shaun the Sheep

0

我和你有完全相同的需求。一个叫做'maybeWeCouldStealAVa'的人已经写了一个很好的实现方法:如何追加AES加密文件

我确认它可以工作,但是当我在每行末尾使用'flush()'时,我会错过消息的最后一部分-多达16个字节-直到下一条消息被写入。我可以在每行末尾使用'close()',因为这似乎是写填充的唯一方法。但至少它不需要读取整个文件才能追加。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接