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

其实这对于保护公钥(公钥的定义是什么呢?)有点傻,但是按照Google的文档 :

为了保护您的公共密钥免受恶意用户和黑客的侵害,请勿将其作为stringembedded到任何代码中。 相反,在运行时从string构造string或使用位操作(例如,XOR与其他string)来隐藏实际的键。 密钥本身并不是秘密信息,但是你不想让黑客或恶意用户用另一个密钥replace公钥。

有没有推荐的方法来做到这一点?

我知道有很多方法可以做到这一点,我不想像过去一样处理密码哈希 (例如md5,sha1等),我想知道上述用例的最佳做法。

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

当然,保护密钥的最好方法就是不要在你的应用中拥有密钥。 将所有的事务validation逻辑移动到您的服务器,并使用HTTPS连接到它。 正确validation证书链以确保您正在与自己的服务器进行通信。 否则,有人可能会搞砸DNS,愚弄你的应用程序连接到自己的服务器。 数星期前,针对iOS采购的类似攻击被宣布。

接下来最好的办法是以某种方式混淆密钥,并将其包含在您的应用中。 这有一个好处,就是你不需要服务器,但是缺点是如果有人确定了,他们就会知道,因为他们总是可以反转你的应用程序的字节码。 所以你最好的办法是拿出你自己的原创的方式来做到这一点,而不是在公共论坛上显示出来:)为了让它更难一点,你可以在本地代码中实现validation部分,这是很难的(但不不可能)分析。 不过,正如上面提到的,在正确的地方修补字节码比试图replace公钥更容易,所以这是大多数cookies会做的。

至less做简单的文字转换。 这个想法是,明确的dex分解不会泄露你的公钥。

这是一个简单的string编码/解码function的例子:

 /** * 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); } 

然后你的私钥作为编码string存储在源文件中(用这个函数编码),并在运行时用相同的函数解码。 这是Google提出的一种“异或”方法。

你自己做'我'的参数,任何随机的,如0x27或其他将工作。 如果以这种方式隐藏更多string,请对每个转换使用不同的“i”。

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

(我是ProGuard和DexGuard的开发者)

将您的公钥存储在服务器端,一旦您从Google Play获得响应,以validation密钥将响应发送到服务器,并在服务器上执行您的操作。

公钥是base64编码的( [a-zA-Z0-9+/] ),所以你可以很容易地避免需要转义混淆string,这是@ PointerNull解决scheme中令人讨厌的问题。

相反,您可以通过首先将有问题的字符转换为6位int来执行混淆。 然后做位操作(例如异或),然后转换回base64编码的字符。 保证没有字符转义需要。