Android应用内结算:保护应用公钥

从Android应用程序计费版本3(TrivialDrive)示例应用程序来与SDK

MainActivity.java

/* base64EncodedPublicKey should be YOUR APPLICATION'S PUBLIC KEY * (that you got from the Google Play developer console). This is not your * developer public key, it's the *app-specific* public key. * * Instead of just storing the entire literal string here embedded in the * program, construct the key at runtime from pieces or * use bit manipulation (for example, XOR with some other string) to hide * the actual key. The key itself is not secret information, but we don't * want to make it easy for an attacker to replace the public key with one * of their own and then fake messages from the server. */ String base64EncodedPublicKey = "CONSTRUCT_YOUR_KEY_AND_PLACE_IT_HERE"; 

那么我不知道我理解这个安全措施。 我知道如何从Google Play开发者控制台获取应用程序的公钥(已经以base 64编码)。

我不了解的是这部分

  /* Instead of just storing the entire literal string here embedded in the * program, construct the key at runtime from pieces or * use bit manipulation (for example, XOR with some other string) to hide * the actual key */ 

据我所知,这个公钥是一个常量string,在应用上传过程中由Google给出。

我们如何使用任何位操作过程以编程方式创build相同的密钥? 有人以前做过吗? 有没有关于如何做到这一点的示例代码?

像这样的东西:

 String Base64EncodedPublicKey key = "Ak3jfkd" + GetMiddleBit() + "D349824"; 

要么

 String Base64EncodedPublicKey key = DecrementEachletter("Bl4kgle") + GetMiddleBit() + ReverseString("D349824"); 

或者任何不会将密钥放在base64明文中的任何string。 也许还有一些不存储在base64中的密钥也是一个好主意,因为原始的base64文本片段很容易被发现。

保护钥匙不是一个特别好的方法。 但是它可以防止一些微不足道的攻击,在这种攻击中,有人只是在你的APK中search文字string,寻找类似于base64编码公钥的东西。 至less你让#$ $ ers工作一点点。

假定邪恶的人可以做坏事,如果他们确定你的公钥。 Google似乎是这么想的。 我可以猜测这一步做了什么,但我不确定我真的想在一个开放的论坛上进行猜测,并给任何人任何想法。 你想这样做。

基本的情节总结就是,让人们更难编写一个应用程序,以编程的方式去除应用程序。

一个人认为,任何人这样做,使生活破解20或30,000 Android应用程序,并重新发布。 很可能,如果他们真的需要做一些手动工作,我想他们不会花费额外的十分钟时间将您的应用程序添加到已被程序破解的20,000个Android应用程序列表中。 除非你有一个顶级的应用程序。 然后这场战斗可能是无止境的,可能最终是徒劳的。

将密钥分割成连续的块(如另一个答案中提出的)可能不够好。 因为密钥将以APK中的string常量表中的连续string结尾。 用程序很容易find。

另一种方法是对密钥进行一些基本的转换。

 // Replace this with your encoded key. String base64EncodedPublicKey = ""; // Get byte sequence to play with. byte[] bytes = base64EncodedPublicKey.getBytes(); // Swap upper and lower case letters. for (int i = 0; i < bytes.length; i++) { if(bytes[i] >= 'A' && bytes[i] <= 'Z') bytes[i] = (byte)( 'a' + (bytes[i] - 'A')); else if(bytes[i] >= 'a' && bytes[i] <= 'z') bytes[i] = (byte)( 'A' + (bytes[i] - 'a')); } // Assign back to string. base64EncodedPublicKey = new String( bytes ); 

所以这个想法是把你的原始密钥作为base64EncodedPublicKey并运行上面的代码,它将交换小写字母和大写字母,并把结果放回到base64EncodedPublicKey 。 然后,您可以从debugging器复制结果并将其作为原始base64EncodedPublicKey值粘贴到代码中。 此时,您的密钥将被转换(大小写切换),并在运行时将其修复回正确的shell,并继续工作。

以上显然是一个相当基本的转码,但你可以更有创意,颠倒AZ的sorting,交换奇数和偶数,交换元音偶数。 这里的问题是,如果我把代码放在上面的代码片段中,那么会有一些更有趣的代码转换,然后每个人都复制并粘贴到他们的项目中,一个黑客就可以很容易地看到和使用代码转换代码这个post)! 所以你只需要自己提出一些转换。

我故意将这两个方向上的工作(所以如果你运行两次,你会得到你原来的价值),因为它可以很容易地运行你的原始密钥的algorithm。 我认为它是一种整洁,它看起来像真正的关键是坐在那里作为纯文本,一个偶然的cookies可能会尝试切换,然后在它不工作时混淆。

你可以把它分成这样的片段

 String piece1 = "SDFGJKGB4UIH234WE/FRT23RSDF/3DFUISDFVWE"; String piece2 = "SDFGJKGB4UIHUISDFVWE"; String piece3 = "BDYASGBDNAWGRET24IYE23das4saGBENWKD"; String piece4 = "432423SDF23R/+SDDS"; mHelper = new IabHelper(this, piece1 + piece2 + piece3 + piece4); 

任何一种操作都可以。

你不能完全从攻击者隐藏公钥,你只需要操纵这个string来混淆攻击者一点点

您可以添加一些string,并在需要时将其删除或将其拆分成块。

我所做的就是将密钥转换成一个char数组,将其分成两部分,然后在需要时重build它,如下所示:

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_shop); char[] base64KeyByteArray = ArrayUtils.addAll(getPublicKeyChunk1(), getPublicKeyChunk2()); Log.d(TAG, String.valueOf(base64KeyByteArray)); } private char[] getPublicKeyChunk1() { return new char[]{82, 73, 67, 66, 73, 106, 65, 78, 66, 103, 107, 113, 104, 107, 105, 71, 57, 119, 79, 66, 65, 81, 69, 70, 65, 65, 79, 67, 65, 81, 56, 65, 77, 73, 73, 66, 67, 103, 75, 67, 65, 81, 69, 65, 121, 55, 81, 76, 122, 67, 105, 80, 65, 110, 105, 101, 72, 66, 53, 57}; } private char[] getPublicKeyChunk2() { return new char[]{82, 43, 68, 47, 79, 121, 122, 110, 85, 67, 118, 89, 108, 120, 43, 49, 80, 100, 67, 108, 55, 90, 57, 103, 119, 57, 87, 78, 79, 111, 53, 101, 80, 71, 117, 74, 104, 82, 87, 97, 100}; } 

有人真的需要你私钥吗? 我认为整个想法是取代它。 恕我直言,任何操作都是无用的。 唯一需要做的事情就是用正确的(他自己的键)值来初始化variables,一行开始google API调用。