来自Android In App Billing版本3(TrivialDrive)示例应用程序随附sdk
/* 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 Developer Console获取应用程序公钥(已经过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
*/
据我所知,这个公钥是一个常量字符串,在应用程序上传过程中由Google提供。
我们如何使用任何位操作过程以编程方式创建相同的键?有人曾经做过吗?有关于如何执行此操作的示例代码吗?
答案 0 :(得分:43)
这样的事情:
String Base64EncodedPublicKey key = "Ak3jfkd" + GetMiddleBit() + "D349824";
或
String Base64EncodedPublicKey key =
DecrementEachletter("Bl4kgle") + GetMiddleBit() + ReverseString("D349824");
或任何未将base64明文中的密钥放在单个字符串中的内容。可能还有一些不在base64中存储密钥的东西也是个好主意,因为原始的base64文本片段很容易被发现。
保护钥匙并不是特别好的方法。但是它可以防止一个微不足道的攻击,有人只是在你的文字字符串中搜索APK,寻找看起来像base64编码公钥的东西。至少你让#$ # $ ers工作了一点。
如果他们确定你的公钥,大概是邪恶的人可以做坏事。谷歌似乎也这么认为。我可以猜到这一步做了什么,但我不确定我是否真的想在一个开放的论坛上推测这一点,并给任何人任何想法。你想这样做。
基本的情节摘要是你要让某人编写一个以编程方式取消LVL应用程序的应用程序更加困难。
有人认为,任何正在这样做的人都会破解20或30,000个Android应用程序并重新发布它们。很可能,我想他们不会花费额外的十分钟时间将你的应用添加到已被程序破坏的20,000个Android应用程序列表中,如果他们实际上需要做一些手工操作的话。除非您有顶级应用程序。然后战斗可能是无止境的,可能最终徒劳无功。
将密钥分成连续的块(如另一个答案中所提出的)可能不够好。因为密钥将以APK中的字符串常量表中的连续字符串结尾。用程序太容易找到了。
答案 1 :(得分:13)
另一种方法是对密钥进行一些基本的转换。
// 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
。然后,您可以从调试器中复制结果并将其作为原始base64EncodedPublicKey
值粘贴到代码中。此时,您的密钥将被转换(大写和小写切换),并且在运行时它将把它修复回正确的外壳,并继续工作。
以上显然是一个非常基本的转码,但你可以更有创意,颠倒A-Z的顺序,交换奇数和偶数,交换元音为偶数。这里的问题是,如果我将代码放在上面的代码片段中,它会执行一些更有趣的代码转换,然后每个人都将其复制并粘贴到他们的项目中,那么一个破解者将能够轻松地自己查看和使用转码(从查看这个帖子)!所以你必须自己想出一些变换。
我故意在两个方向上完成上述工作(因此,如果你运行两次,你将获得原始值),因为它可以很容易地在原始密钥上运行算法。我觉得它有点整洁,看起来真正的钥匙就像纯文本一样坐在那里,一个随意的饼干可能会试图切换它然后在它不起作用时感到困惑。
答案 2 :(得分:5)
您可以将其拆分为此类
String piece1 = "SDFGJKGB4UIH234WE/FRT23RSDF/3DFUISDFVWE";
String piece2 = "SDFGJKGB4UIHUISDFVWE";
String piece3 = "BDYASGBDNAWGRET24IYE23das4saGBENWKD";
String piece4 = "432423SDF23R/+SDDS";
mHelper = new IabHelper(this, piece1 + piece2 + piece3 + piece4);
任何类型的操作都可以。
你无法完全隐藏攻击者的公钥,你只需操纵字符串就可以让攻击者稍微混淆
您可以添加一些字符串并在需要时将其删除或将其拆分为块。
答案 3 :(得分:2)
我所做的是将密钥转换为char数组,将其拆分为两个,然后在需要时重建它,如下所示:
@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};
}
答案 4 :(得分:0)
我们可以使用Gradle来保护API密钥或密钥。检查我的answer。
答案 5 :(得分:0)
在Steven Craft's Answer的帮助下,以gidds为基础
这是一个更干净的代码。 此外,它将数字(0-9)换成ASCII字符(37-46),反之亦然。写在科特林。
val string = "Hello World 012345679 %&()"
fun String.swapCase() = map {
when {
it.isUpperCase() -> it.toLowerCase()
it.isLowerCase() -> it.toUpperCase()
it.isDigit() -> (37 + (it.toInt() - 48)).toChar()
it.isDefined() -> if (it.toInt() >= 37 && it.toInt() <= 46) (48 + (it.toInt() - 37)).toChar() else it
else -> it
}
}.joinToString("")
println(string.swapCase()) // hELLO wORLD %&'()*+,. 0134
使用此-> https://edge-developer.github.io/BillingGenerator/即时生成所有
答案 6 :(得分:-3)
有人真的需要你的私钥吗?我认为整个想法是替换它。恕我直言,任何操纵都是无用的。邪恶者唯一要做的就是用正确的(他自己的密钥)值初始化变量,一行是谷歌API调用。