Android中base64编码公钥的强加密

信息安全 加密 安卓
2021-08-24 10:38:42

我想知道如何对我的 Android 应用程序中的公钥进行强加密。

这是Android的建议

为了保护您的公钥免受恶意用户和黑客的攻击,请勿将您的公钥嵌入为整个文字字符串。相反,在运行时从片段构造字符串或使用位操作(例如,与其他字符串进行异或)来隐藏实际密钥。密钥本身不是秘密信息,但您不想让黑客或恶意用户轻易地用另一个密钥替换公钥。

给出了某些解决方案,例如具有子字符串和加密,但我想知道如何以有效的方式实现它。

3个回答

首先,请注意,您需要的不是加密。这个建议是关于公钥的。顾名思义,公钥不是秘密的(有时为了隐私除外——但当您的应用程序的密钥在您的应用程序中时,就不会涉及隐私)。您需要确保公钥的完整性,即确保恶意实体无法用不同的密钥替换它。

应用程序使用公钥来验证采购订单。购买的正常事件顺序是:

  1. 用户联系 Google 服务器并支付一些钱来购买应用内功能。
  2. Google 服务器为该购买开具收据。它使用永不离开服务器的私钥签署此收据。
  3. 您在移动设备上运行的应用程序会下载收据。
  4. 您的应用程序根据与应用程序捆绑的公钥来验证收据是否真实。
  5. 如果购买是可重复的(例如,允许下载 X 分钟的受保护内容,而不是解锁功能),则应用程序必须确保同一张收据不能被使用两次(重放攻击)。它通过“消费”购买来做到这一点。

问题是用户可能会修改您的应用程序的代码或数据以放置他选择的公钥而不是真正的公钥。特别是,他可以放置一个他知道私钥的公钥。如果他这样做,他可以在不通过任何服务器的情况下生成购买收据,并且您的应用程序将在第 4 步接受它们为真实的。

为了防止这种攻击,您需要做的是检测任何修改公钥的尝试。潜在的攻击者是否可以读取公钥并不重要,只要他无法更改即可。这意味着您的应用程序应包含验证密钥是否真实的代码。但无论你做什么,攻击者都可以更改验证码(只需在某处翻转一下即可更改if is_genuine(public)key)if not(is_genuine(key)))......

所以你需要让攻击者无法找到验证码。不仅如此:您必须让他无法跳过验证码并进入有趣的部分。您需要混淆整个应用程序。但是混淆即使不是不可能也很难

只有两种方式可以从混淆中受益:

  • 如果没有人关心你的应用程序,也许没有人会尝试破解它。(缺点:你也没有赚钱。)
  • 你付出了很多努力,只希望它能坚持一小段时间。请注意,每个版本都必须付出巨大的努力:如果使用相同的混淆技术发布了很多软件,那么有人会找到破解它的方法,并且所有这些软件都会暴露出来。

对于混淆的成功故事,我建议阅读Gavin Dodd 关于游戏Spyro: YOTD的故事。关键是它花费了很多努力,目标只是将破解延迟几个月,并且它部分依赖于攻击者的心理,他们只花有限的时间攻击每场比赛并停下来他们一跨过第一道关卡。

在大多数情况下,混淆的成本远远超过它能给你带来的好处。

所以,你可以做什么?如文章中所述:不要在设备上验证购买,而是在您控制的服务器上验证。这仅在购买结果来自服务器时才有用。例如,如果购买的是附加内容或功能,则收据应解锁服务器上用户帐户中的内容,并且应用程序将下载服务器允许它拥有的任何内容。

无论您使用什么加密,它仍然在客户端的设备上,因此他们可以解密它。您遇到了与 DRM 系统相同的问题,即您移交给用户的任何内容都可以被修改。

如果您的应用程序的安全性取决于您的公钥的保密性,那么您的架构存在根本缺陷,需要从不同的角度解决问题。

如果您只是试图阻止用户更改公钥以便他们可以使用自定义私有服务器,那么您最多可以做的就是混淆它并希望最好。

@Polynomial 几乎像往常一样钉牢了它,但是为了扩展他的意思obfuscate

正如 android 文档所建议的那样,您想让公钥从二进制文件中提取出来有点困难。您基本上有两层保护;

  1. 使用一些相当复杂的方法在运行时构建密钥。XOR 很好,某种迭代很好,转置和替换也很好。
  2. 混淆您的密钥派生机制。我的意思是对您的代码使用反调试技术。很少有开发人员能达到这种程度,但这一切都有帮助。