前言

Android开源,开源就意味着无线可能和无线的不安全。现在(2016)市面上的所有Android安全方法基本上有以下几种:

1.代码混淆。

2.so处理重要逻辑。

3.加壳

这些都是在客户端做的处理,然而,如果破解客户端能获取的利益大于破解的难度,那么基于开源的Android基本还是会被”破解大军”进行”三光政策”的。既然都会被破解,那还做这些做什么呢?这就是我之前文章说的,利益和难度的取舍。当我们做了以上3部后,就已经阻绝绝大部分的”破解军”,剩下的哪些顶尖人物怎么办呢?现在我的处理方法是放在服务端。

问题

要解决问题,首先要有问题,那么对于客户端来说什么是危险的呢?举个栗子,当用户注册的时候,如果明文传输就有可能被拦截到,泄漏用户密码的问题。正对这个问题,我来叙述一下自己的解决方案,顺便把这篇文章的重点带出来。

解决

问题:用户注册和服务端交互的信息有可能被拦截,导致账户等信息泄露。

方法1

将用户密码进行MD5后再传递。

这种方法也就保证了我们自己也无法知道用户的密码是什么。即使被拦截,破解军获取到这段信息也无法得知密码是什么。

PS:这种方法是可取的,但是如果用户的密码比较简单,那也是可以通过暴力破解出来的。所以MD5的方法比较适合用来确保数据的正确性,而不适合作为数据的保密处理。

方法2

使用特殊算法进行加密后在传递。

这种方法可以确保即使被拦截到信息,在不知道我们算法的前提下,破解军也无法获取有用信息。

不过这里有两个问题,第一是算法在破解后很容易查询到,即使是存放在so文件中。第二是这种自己定义算法对性能的要求可能比较高,毕竟我们又不是数学专家。

当然为了更坚固的堡垒,提高破解军的成本,该方法是可以结合使用的。

方法3

使用AES加密报文后在传递。

这种方法和方法2类似,只是AES是当下确定能很好加密数据,且很难暴力破解的方案。当然加密就要解密,而AES的加密和解密使用的通一个key值。那么就需要客户端存储一个key值,既然该key值存在客户端,那么破解的可能性就很大了。针对这个问题,有一个弯路可以考虑,那就是隐藏key值。

这里就记录一下隐藏key值的小故事,该方法不单是隐藏key值,也可以隐藏很多东西,增加破解的成本。

好,假设我们使用了AES加密,那么就有一个key值,那么我们应该怎么存这个key在客户端呢?

方法基本有以下这几种:

SharedPreferences

Java硬编码

NDK保存在so

发现,除了NDK的方法有点难度,其它两种基本都是新手破解军都能搞定的事,那么怎么办呢?那我就给他来个大杂烩别(年轻人啊)。首先我把key分成了4份。

key = “whitelaning”;

key1 = “wh”;

key2 = “ite”;

key3 = “lan”;

key4 = “ing”;

当需要使用key的时候分别获取4段可以值合并后才能得到真正的key。

key1写在string.xml中

mContext().getResources().getString(R.string.something1); 。

ps:为什么叫something1呢,年轻人不懂事…

key2写在AndroidManifest.xml中

<meta-data android:name=”something2″ android:value=”ite”/> 。

key3写在so文件中。

#include "com_jni_JNIUtils.h" JNIEXPORT jstring JNICALL Java_com_jni_JNIUtils_getString (JNIEnv *env, jobject obj) { 
return (*env)->NewStringUTF(env, "something3");
} //--------------------------------------- key3 = new JNIUtils().getString();

key4写在assets的文件中。

Context.getAssets().open(“something4.txt”)

然后…破解的难度提高了,而且也把以后的开发者逼疯了…哈哈…(弃用)

方法4(使用中)

客户端 –> 服务端

客户端使用随机生成的AES密钥加密传输数据,使用RSA公钥加密AES的密钥。

服务端使用RSA私钥解密出AES的密钥,再使用AES的密钥解密加密的数据。

服务端 –> 客户端

服务端使用RSA解密出AES的密钥后,使用该AES密钥解密数据,然后进行业务处理。业务处理完毕后,使用该AES密钥对数据进行加密,返回给客户端。

客户端接收到返回数据后,使用之前请求时随机生成的AES密钥进行解析,然后废弃该AES密钥。

以上就是一次完整的请求交互过程,当然省略了一些细节上的处理和具体业务。比如数据应该使用MD5来验证数据的完整性,接口验证等等。

方法4有点类似 SSL/TLS 协议握手的原理,当然因为Android是开源的,没必要完全按照 SSL/TLS 协议来实现,毕竟做安全问题的时候,我都是默认我的源码被盗了的情况下去做的。

 

 

来自:http://www.jianshu.com/p/84636b4b21d2