2012-07-26 72 views
40

其实这是一个有点傻关于保护公共密钥(什么是公共密钥的定义呢?),但作为每documentation by Google如何保护做应用程式内结算时,谷歌播放公钥

为了保持您的公共密钥不受恶意用户和黑客的侵害,因此不要将 作为文字字符串嵌入到任何代码中。相反,在运行时从零件构造 字符串或使用位操作(例如, XOR与其他字符串)来隐藏实际的键。密钥本身并不是秘密信息,但您不希望让黑客或恶意用户轻易地用另一个密钥替换公钥。

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

我知道有很多方法可以做到这一点,我只是不希望用同样的方法的人如何处理密码在过去的散列(例如MD5,SHA1等),我想知道的最佳实践在上面的用例中。

回答

35

在这里出现很多:)您引用的段落背后的想法是,为了保证应用内结算安全,您需要验证交易签名。这些使用与您的开发者帐户相关联的私钥进行签名。关键在于Google的服务器,所以假设没有其他人可以用它来签署数据是相当安全的。要验证它,您需要您的公钥,您可以从开发者控制台复制该公钥。如果有人在您的应用中替换了它,他们可能会欺骗它接受来自未授权来源的应用内结算交易,因为如果他们种植公钥,他们可能也会控制相应的私钥。然而,在实践中,只需在正确的位置修改代码,以便始终为isLicensed()hasItem()或您可能具有的类似方法返回true,并且没有人执行此操作,则更容易。

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

接下来最好的办法是以某种方式混淆密钥,并将其包含在您的应用中。这样做的好处是你不需要服务器,但缺点是如果有人足够肯定,他们会发现它,因为它们总是可以颠倒你的应用程序的字节码。所以你最好的选择是提出你自己的原创方式,它不会在公共论坛上显示出来:)为了让它更难一点,你可以在本地代码中实现验证部分,这很难(但不是不可能)分析。不过,正如上面提到的,在正确的位置修补字节代码比试图替换公钥更容易,所以这就是大多数破解者所要做的。

+1

你是什么意思“然而,在实践中,在正确的位置简单地修改你的代码总是为isLicensed(),hasItem()或类似的方法你可能有,没有人这样做。“?这句话没有完全意义。请澄清。 – Stunner 2013-01-16 21:41:22

+10

这意味着修补应用程序并彻底禁用您可能拥有的任何许可检查会更容易,而不是尝试更换密钥和混乱尝试欺骗签名验证。 – 2013-01-17 01:06:53

+0

〜“**可能也会控制相应的私钥**”。但是,应用内结算请求会通过设备上的Play Store APK进行。那么,某人如何控制或操纵该逻辑? – 2016-09-02 14:29:36

4

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

+1

这假定有一个这样的服务器端基础设施建立。 – 2016-09-02 14:40:40

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

然后您的私人密钥被存储在源作为编码的字符串(与此功能进行编码的话),并在具有相同功能的运行时解码。这是Google建议的一种“异或”方法。

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

+14

神秘:)如果你是程序员,你肯定会克服这样的问题。 – 2012-08-02 10:02:30

+2

@NPike,你需要转义字符串才能在Java中使用它。试试这个网站:http://www.htmlescape.net/javaescape_tool.html不幸的是,我发现转换过程通常会导致Eclipse无法应对的字符串(即使在转义时),所以您必须调整直到你得到一些你可以使用的值... – 2013-06-11 23:47:03

11

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

(我的ProGuard和DexGuard的开发者)

+0

真棒!谢谢..异或方法是安全的?? – 2012-08-28 10:26:53

+1

DexGuard是否仅仅是对一个简单的字符串进行混淆就是矫枉过正?我的意思是,无论如何,它能做到这一点的保证是什么? – 2016-09-02 14:39:53

1

公钥是base64编码([a-zA-Z0-9+/]),这样你可以很容易地避免需要躲避混淆字符串,就好象是在@ PointerNull的一个恼人的问题解。

相反,您可以通过首先将相关字符转换为6位整数来执行混淆处理。然后进行位操作(例如异或),然后转换回base64编码的字符。保证不需要角色转义。

相关问题