进行InApp结算时如何保护Google Play公钥

Rya*_*yan 42 java android google-play

实际上这对于保护公钥有点愚蠢(那么公钥的定义是什么?)但是根据Google文档:

为了保护您的公钥免受恶意用户和黑客的攻击,请不要将其作为文字字符串嵌入任何代码中.相反,在运行时从片段构造字符串或使用位操作(例如,XOR与其他字符串)来隐藏实际的键.密钥本身不是秘密信息,但您不希望黑客或恶意用户轻易用其他密钥替换公钥.

有没有推荐的方法呢?

我知道有很多方法可以做到这一点,我只是不想按照人们过去处理密码哈希的方式(例如md5,sha1等),我想知道上述用例中的最佳实践.

Nik*_*kov 38

这里出现了很多:)你引用的段落背后的想法是,为了使应用程序内的计费安全,你需要验证交易签名.这些是使用与您的开发者帐户相关联的私钥签名的.密钥位于Google的服务器上,因此可以相当安全地假设没有其他人可以使用它来签署数据.要验证它,您需要公钥,您可以从开发人员控制台复制该公钥.如果有人在您的应用中替换了它,他们可能会欺骗它接受来自未经授权的来源的应用内结算交易,因为如果他们种植公钥,他们可能还会控制相应的私钥.然而,在实践中,简单地在正确的位置修改代码以便总是返回true isLicensed(),hasItem()或者使用类似的方法,并且没有人这样做会容易得多.

当然,保护密钥的最佳方法是不要在应用程序中使用密钥.将所有事务验证逻辑移动到您的服务器,并使用HTTPS连接到它.正确验证证书链,以确保您与自己的服务器通信.否则,有人可能会乱用DNS并欺骗您的应用程序连接到他们自己的服务器.几周前就宣布了针对iOS采购的类似攻击.

下一个最好的方法是以某种方式混淆密钥,并将其包含在您的应用程序中.这样做的好处是您不需要服务器,但缺点是,如果有人确定了足够的数据,他们会解决问题,因为他们总是可以反转应用程序的字节代码.因此,最好的办法是提出自己独创的方式,而不是出现在公共论坛上:)为了使它变得更难,你可以在本机代码中实现验证部分,这更难(但不是不可能)分析.尽管如此,如上所述,在正确的位置修补字节代码比尝试替换公钥要容易得多,因此大多数破解者都会这样做.

  • 这意味着更容易修补应用程序并彻底禁用您可能拥有的任何许可检查,而不是尝试替换密钥和混乱尝试欺骗签名验证. (10认同)

Poi*_*ull 32

至少做简单的文本转换.这个想法是普通的dex反汇编不会泄露你的公钥.

这是一个简单的字符串编码/解码函数示例:

/**
 * Simple String transformation by XOR-ing all characters by value.
 */
static String stringTransform(String s, int i) {
   char[] chars = s.toCharArray();
   for(int j = 0; j<chars.length; j++)
      chars[j] = (char)(chars[j] ^ i);
   return String.valueOf(chars);
}
Run Code Online (Sandbox Code Playgroud)

然后,您的私钥作为编码字符串存储在源中(使用此函数对其进行编码),并在运行时使用相同的函数进行解码.这是Google建议的一种"XOR"方法.

你自己制作'i'参数,任何随机的东西,如0x27或其他都可以.如果以这种方式隐藏更多字符串,请为每个转换使用不同的"i".

  • 神秘:)如果你是程序员,你肯定会克服这个问题. (14认同)
  • @NPike,你需要转义字符串才能在Java中使用它.试试这个网站:http://www.htmlescape.net/javaescape_tool.html不幸的是,我发现转换过程经常会导致Eclipse无法处理的字符串(即使在转义时),所以你必须调整在您获得可以使用的东西之前,该值被异或 (2认同)

Eri*_*une 11

作为手动模糊密钥的替代方法,您也可以让混淆器自动执行.ProGuard是Android SDK的一部分,但它主要模糊了类/字段/方法名称,而不是字符串.它的Android专用兄弟DexGuard可以添加更多层混淆,应用字符串加密,类加密和反射.它不是免费的,但它可以节省时间,而且可能比手动操作更有效.

(我是ProGuard和DexGuard的开发人员)