Java 在进行InApp计费时如何保护Google Play公钥

Java 在进行InApp计费时如何保护Google Play公钥,java,android,google-play,Java,Android,Google Play,实际上,保护公钥有点愚蠢(那么公钥的定义是什么?),但根据: 为了保护您的公钥免受恶意用户和黑客的攻击,请不要 将其作为文本字符串嵌入到任何代码中。相反,构建 运行时从片段中提取字符串或使用位操作(例如, 使用其他字符串的XOR)隐藏实际键。关键是 不是秘密信息,但你不想让一个 黑客或恶意用户将公钥替换为其他密钥 有什么推荐的方法吗 我知道有很多方法可以做到这一点,我只是不想效仿过去人们处理密码哈希的方式(例如md5、sha1等),我想知道上述用例中的最佳实践。将公钥存储在服务器端,一旦收到来自

实际上,保护公钥有点愚蠢(那么公钥的定义是什么?),但根据:

为了保护您的公钥免受恶意用户和黑客的攻击,请不要 将其作为文本字符串嵌入到任何代码中。相反,构建 运行时从片段中提取字符串或使用位操作(例如, 使用其他字符串的XOR)隐藏实际键。关键是 不是秘密信息,但你不想让一个 黑客或恶意用户将公钥替换为其他密钥

有什么推荐的方法吗


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

将公钥存储在服务器端,一旦收到来自google play的验证密钥的响应,将该响应发送到服务器并在服务器上执行操作。

至少进行简单的文本转换。这个想法是,普通的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);
}
/**
*通过按值对所有字符进行异或运算实现简单的字符串转换。
*/
静态字符串stringTransform(字符串s,int i){
char[]chars=s.toCharArray();

对于(intj=0;j这在这里经常出现:)你引用的段落背后的想法是,为了保证应用内计费的安全性,你需要验证交易签名。这些签名是用与你的开发者帐户关联的私钥签名的。该密钥驻留在谷歌的服务器上,因此假设没有其他人可以用它签名是相当安全的。要验证它,你需要你的公共密钥密钥,您可以从开发人员控制台复制。如果有人在您的应用程序中替换它,他们可能会欺骗它接受来自未经授权来源的应用程序内计费交易,因为如果他们植入公钥,他们可能还控制相应的私钥。但是,实际上,只需在正确的位置修改代码就容易得多对于
isLicensed()
hasItem()
或您可能拥有的类似方法,ces始终返回true,但没有人这样做

当然,保护密钥的最佳方法是根本不在应用程序中使用密钥。将所有事务验证逻辑移动到服务器,并使用HTTPS连接到服务器。正确验证证书链,以确保您正在与自己的服务器对话。否则,有人可能会摆弄DNS,欺骗你的应用程序连接到他们自己的服务器。几周前,针对iOS购买的类似攻击已经宣布


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

作为手动混淆密钥的替代方法,您也可以让混淆器自动执行。是安卓SDK的一部分,但它主要混淆class/field/method名称,而不是字符串。它的Android专用同级可以添加更多的混淆层,应用字符串加密、类加密和反射。它不是免费的,但它节省时间,而且可能比手动操作更有效


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

公钥是base64编码的(
[a-zA-Z0-9+/]
),因此您可以轻松避免转义模糊字符串的需要,因为这是@PointerNull解决方案中一个恼人的问题


相反,您可以通过首先将相关字符转换为6位int来执行模糊处理。然后执行位操作(例如XOR ing)然后再转换回base64编码的字符。保证不需要字符转义。

神秘:)如果你是程序员,你肯定能解决这个问题。@NPike,你需要转义字符串才能在Java中使用它。试试这个网站:不幸的是,我发现转换过程经常会产生Eclipse无法处理的字符串(即使在转义时),因此您必须调整被XORD的值,直到您得到可以使用的东西……您的意思是什么“然而,在实践中,简单地在正确的位置修改您的代码以始终为isLicensed()、hasItem()或您可能拥有的类似方法返回true要容易得多,而且没有人这样做。”?这句话没有完全的意义。请澄清。这意味着更容易修补应用程序并彻底禁用您可能进行的任何许可检查,而不是尝试替换密钥并试图愚弄签名验证。~“可能还控制相应的私钥”.但应用内计费请求通过设备上的Play Store APK进行。那么,有人如何控制或操纵这种逻辑呢???@IgorGanapolsky当他们构建一个新的修改过的APK时,他们可以模拟购买,而不必去Play Store(比如luckypatcher)因此,他们可以用修改过的公钥对应的签名对你的应用程序响应一个有效的购买字符串。DexGuard仅仅混淆一个简单的字符串不是很过分吗?我的意思是,如何保证它能正确地完成?假设你已经设置了这样的服务器端基础设施。