声明:每个字都是自己敲的,绝对有干货,还没时间排版,抱歉;
加密和签名
我们的app和服务器有什么安全隐患?
1)窃听;如果你连接了不安全的免费wifi,然后登录我们的app,
如果你的数据没有加密,你的密码是不是就可能被盗?
2)篡改或冒充;万一黑客截获了app给服务器发送的请求数据,然后
稍作修改,发送给服务器,实现修改服务器数据的目的;
3)重放;万一黑客截获了app给服务器发送的请求数据,(哪怕是
加密过的),然后冒充app向服务器发送重复的请求,服务器
会不会被堵死?
4)如果黑客反编译app,修改逻辑(比如放松一些前端的检查规则),
重新打包运行(运行在黑客自己的手机上,不需要重新签名),
由于没有动加密和签名机制,所以在server看来,请求完全来自
可信的app,咋办?
怎么解决?
针对问题1,我们的网络通信数据需要加密,这样黑客
就看不到真实数据了;
针对问题2,我们需要给数据加签名,如果黑客截获并
修改了数据,则服务器会发现解密后的数据和
原数据不匹配,知道这是一份被修改过的数据,拒绝处理;
针对问题3,引入图片验证码和token机制,登录的时候
要求用户在app输入图片验证码,登录后服务器返回
一个动态生成的token给app,之后app的所有请求必须
携带这个token;当服务器遇到来自这个token的频繁的
重复请求的时候,立即让这个token失效,拒绝来自这个
token的后续所有请求,同时让app退出登录,
要求用户重新做一次登录操作;
(疑问:为什么微信支付宝没有这个机制?体验不好?)
解决方法2:时间戳+token方案;每个请求带一个时间戳,
这个时间戳和其他数据绑在一起并统一加密,所以黑客
无法单独修改时间戳,如果服务器遇到来自同一个token的
相同时间戳的请求,即可断定这是一次重放攻击,让token失效;
(疑问:如果支持多点登录,则2台手机上app理论上有可能
发起相同时间戳的请求,服务器会误杀吗?
解决办法:2个手机上的app使用独立的token,但是登录
的时候除了用户名密码还需要传设备信息用来区分不同手机咯)
针对问题4:所以说只在前端加限制是不够的,后端必须再做一次
检查,这样就没事了;
理论:
建议参考《改变未来的九大算法》,通俗易懂;
密钥生成算法:
1)随机选取2个足够大的不同素数p和q;
(最好保证下文的n是1024位二进制长度)
2)计算p和q的乘积n;
3)计算n的欧拉函数r = (p-1)*(q-1);
4)随机取一个整数e,要求1 < e < r,且e与r互质;
5)计算e对于n的模反元素d;
6)将(n,e)作为公钥,(n,d)作为私钥;(其实可以互换);
7)假设原数据是一个整数m,则加密结果为c=m^e%n;
8)解密过程是c^d%n,可以证明这个结果等于原数据m;
对于任意需要加密的字符串abc,我们可以将每个字母
分开,然后每个字母转成ASCII码,再对每个整数单独加密;
从上文的分析,你也能发现,rsa加密过程比较费时,
一种改进策略是用对称加密算法加密数据,这个算法比较快,
然后将这个对称密钥本身用rsa非对称密钥加密;
这个算法安全性来自于:别人无法根据(n,e)轻易推断出(n,d),
为了推出d,你需要得到r,一种方法是暴力计算,复杂度
很高;另一种方法是先推断p和q,这属于大数分解问题,
复杂度也很高;另外,不要忘了,e的选取不是唯一的,
d的值也不是唯一的,这又增加了破解的复杂度;
注:要想真的理解以上算法,建议多读几篇参考文献;
细节:
1)加密
考虑app请求服务器的场景;
app用server的公钥加密数据;
Server用server的私钥解密数据;由于只要server知道
自己的私钥,所以黑客无法破解数据;
反过来,考虑服务器给app返回数据的场景;
server用app的公钥加密数据;
App用自己的私钥解密数据;由于只有app知道自己的
私钥,所以黑客无法破解数据;
(疑问:app的私钥如何保存?)
2)签名
还是考虑app请求服务器的场景;(反过来的情况类似)
App用app的私钥加密数据,然后将加密后的数据连同
原数据传给服务器;
Server用app的公钥解密数据,如果得到的数据和原数据
相同,则证明这个数据的确来自app(可能被截获过,
但至少是没被篡改过的),否则证明这个数据不是来自app
的或者被篡改过;
(疑问:app的私钥怎么保存?如果只是简单的写在代码里,
由于字符串不会被混淆,岂不是会被看到?
放在so里的字符串也能被反编译;黑客也可以调用
Jni接口骗取私钥,所以jni方案不行)
改进:
由于原数据可能比较长,直接加密数据比较慢,
可以由原数据得到较短的md5摘要,然后对摘要做加密;
(md5的原理请百度)
Base64是什么鬼,和加密有什么关系?
请自行百度,大概意思是:
现有的网络协议会将不可见字符删除,导致你的数据发生变化,
所以我们需要将数据全部变成可见字符,然后再传输;
Base64的确让数据变的不可读了,但是这个过程是可逆的,
所以不能算加密;
这儿谈的签名和apk签名有什么关系?
没有关系,数据签名是为了验证server或者app的身份;
Apk签名是为了验证apk的真实来源;
签名算法是一样的,但是对象不一样;
双向都需要做加密和签名吗?
1)加密需要双向都做;
2)签名也需要双向都做;server需要判断请求是否来自app;
App需要判断返回值是否来自server;虽然重要数据都在server端,
但是完全有可能,黑客劫持某个返回值,向app注入虚假数据,然后
App傻乎乎的将这些数据写入了server;
如果用https,数据的双向加密好做,server端的签名也好做,
问题是怎么做app端的签名?
上文提到的私钥和公钥怎么生成?
TODO
keytools
说了这么多,具体怎么编程?
TODO
有没有鸡生蛋的悖论?
登录接口有点特殊啊,它是获取token的接口,所以这个接口
本身是不带token的,那如何预防重放攻击呢?
登录前app也会调用一些接口,比如抓取广告图;
那些允许不登录即可使用的app,也会调用很多不带
token的接口,这些接口如何预防重放攻击?
答:这些接口既然不带身份信息,不会危害用户数据,
最多卡死服务器;不处理行吗?
关键问题:
1)App端如何安全的存储私钥?
答:没有好办法;
那https怎么解决app端签名的私钥存储问题?
2)为什么不直接用https?
答:就是应该用;
3)如果用了okHttp/AsyncHttpClient等第三方库,怎么使用https?
答:我google过了,有现成的解决方案;
4)我们现有的加密和签名机制有什么问题?
答:即使做代码混淆,黑客也能看出大概算法,另外密钥作为常量写
在代码里,不会被混淆,也会被看到;所以整个加密和签名算法
都能被破解;
结论:
用https;可以用自己的证书,省钱,但是要修改认证逻辑;
参考文献:
1) 《改变未来的九大算法》
2)https原理:证书传递、验证和数据加密、解密过程解析
http://blog.csdn.net/clh604/article/details/22179907
3)Android security - Implementation of Self-signed SSL certificate for your App.http://www.codeproject.com/Articles/826045/Android-security-Implementation-of-Self-signed-SSL
4)Android programming: connect to an HTTPS server with self-signed certificate
http://littlesvr.ca/grumble/2014/07/21/android-programming-connect-to-an-https-server-with-self-signed-certificate/
5)数字签名原理剖析
http://blog.csdn.net/turkeyzhou/article/details/4668045
6)two-way SSL
https://gist.github.com/jorgevila/4984072
7)One Way and Two Way SSL and TLS
http://www.ossmentor.com/2015/03/one-way-and-two-way-ssl-and-tls.html
8)HTTPS with Client Certificates on Android
http://chariotsolutions.com/blog/post/https-with-client-certificates-on/
9)android-ssl
https://github.com/rfreedman/android-ssl
10)Everything You Ever Wanted to Know About SSL (but Were Afraid to Ask)
http://www.robinhowlett.com/blog/2016/01/05/everything-you-ever-wanted-to-know-about-ssl-but-were-afraid-to-ask/
中文版:http://www.oschina.net/translate/everything-you-ever-wanted-to-know-about-ssl
11)理解RSA算法的3篇好文章:
http://blog.csdn.net/sunmenggmail/article/details/11994013
RSA算法原理(一)
http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html
RSA算法原理(二)
http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html