几种保存静态秘钥方式的优劣势:
- 密钥直接明文存在sharedprefs文件中,这是最不安全的。
- 密钥直接硬编码在Java代码中,这很不安全,dex文件很容易被逆向成java代码。
- 将密钥分成不同的几段,有的存储在文件中、有的存储在代码中,最后将他们拼接起来,可以将整个操作写的很复杂,这因为还是在java层,逆向者只要花点时间,也很容易被逆向。
- 用ndk开发,将密钥放在so文件,加密解密操作都在so文件里,这从一定程度上提高了的安全性,挡住了一些逆向者,但是有经验的逆向者还是会使用IDA破解的。
- 在so文件中不存储密钥,so文件中对密钥进行加解密操作,将密钥加密后的密钥命名为其他普通文件,存放在assets目录下或者其他目录下,接着在so文件里面添加无关代码(花指令),虽然可以增加静态分析难度,但是可以使用动态调式的方法,追踪加密解密函数,也可以查找到密钥内容。
产中需要保存的秘钥: 由于app需要与服务器交互所以这时候若用户为登录则客户端需要一个默认的秘钥来确认App的游客身份,因此需要在app中保存一个默认的请求秘钥。
- 当用户未登录或者是退出登录时,请求服务器使用默认的秘钥字符串;
- 当用户登录时使用从服务器或其的秘钥字符串; 这样我们需要在App端保存一个默认的秘钥字符串用于标识用户的游客身份,而一个问题就是如何保证秘钥字符串的安全性?
考虑到的其他几种保存秘钥方式:
- 通过保存文件的方式保存秘钥信息:显而易见的通过保存文件的方式保存秘钥信息,有一个问题就是,如果用户恶意删除App保存的秘钥信息,那么App就无法使用默认的秘钥信息了,这样秘钥的唯一性也就无法保证。
- 通过数据库的方式保存秘钥信息:和通过文件的方式保存秘钥信息一样,通过数据库保存也是无法保证恶意用户删除数据库信息,这样我们的App就丢失了默认的秘钥信息。
- 通过配置gradle的方式保存秘钥信息:我们通过下面的gradle配置变量的方式,来讲解如何在gradle配置变量信息。
- 通过配置string.xml的方式保存秘钥信息;
通过Gradle配置: 在gradle文件中我们可以配置静态变量,只需在如下路径添加信息即可:
buildType->debug/release->buildConfigField("String","appKey",""123"")
第一个参数为类型、第二个参数为名字,第三个参数为值,均为String类型,Java代码中需要改变量的值时可以利用BuildConfig.appKey来获取。
通过string.xml: 比如在string.xml文件中存储了一个名为app_key的变量,为一个textview等取值
textView.getContext().getResources().getString(R.string.app_key)
产品中保存静态秘钥实践:
- 第一部分通过gradle配置静态变量;
- 第二部分通过Java硬编码;
- 第三部分通过Java字符串拼接;
- 第四部分通过string.xml保存。
获取第一部分秘钥
public static String getBK1() {
return BuildConfig.appKey;
}
获取第二部分秘钥:这部分的appKay字符串是通过运算的出来的,这里的运算可以是任意运算方式,越复杂越好,越让人看不懂越好,当然结果需要时唯一的。
public static StringBuffer getBk2() {
StringBuffer sb = new StringBuffer();
sb.append(Config.getGBS(2, 5));
return sb;
}
public static int getGBS(int x, int y){
for(int i = 1; i<= x * y; i++){
if(i % x == 0 && i % y == 0)
return i;
}
return x * y;
}
获取第三部分秘钥: 这里可以使用简单的字符串硬编码
public static String getBK3() {
return "xhxh";
}
获取第四部分秘钥
//在string.xml中定义appKey的第四部分
<string name="bk4">chs</string>
//在代码中获取string中定义的字符串值
public static String getBk4() {
mContext().getResources().getString(R.string.bk4);
}
获取最终的appKey字符串:
public static byte[] getDefaultKey() {
StringBuffer sb = new StringBuffer();
sb.append(getBK1())
.append(getBK2())
.append(getBk3())
.append(getBk4());
return sb.toString();
}