Android网络请求中的安全问题

以下是我在开发公司产品的时候遇到的问题,写下来备忘,有时间再整理格式;


加密和签名

 

我们的app和服务器有什么安全隐患?

1)窃听;如果你连接了不安全的免费wifi,然后登录我们的app

如果你的数据没有加密,你的密码是不是就可能被盗?

2)篡改;万一黑客截获了app给服务器发送的请求数据,然后

稍作修改,发送给服务器,实现修改服务器数据的目的;

3)重放;万一黑客截获了app给服务器发送的请求数据,(哪怕是

加密过的),然后冒充app向服务器发送重复的请求,服务器

会不会被堵死?

4)如果黑客反编译app,修改逻辑(比如放松一些前端的检查规则),

重新打包运行(运行在黑客自己的手机上,不需要重新签名),

由于没有动加密和签名机制,所以在server看来,请求完全来自

可信的app,咋办?

 

 

怎么解决?

针对问题1,我们的网络通信数据需要加密,这样黑客

就看不到真实数据了;

 

针对问题2,我们需要给数据加签名,如果黑客截获并

修改了数据,则服务器会发现解密后的数据和

原数据不匹配,知道这是一份被修改过的数据,拒绝处理;

 

针对问题3,据文献,https能防止重放攻击,但是我还没搞懂原理,TODO

 

针对问题4:所以说只在前端加限制是不够的,后端必须再做一次

检查,这样就没事了;

 

 

问题:我们现有的加密机制有什么问题?

答:我们现在用的是AES对称加密,黑客可以反编译代码,

看到算法和密钥,然后截获并破解密文;

 

问题:我们现有的签名机制有什么问题?

答:我们现在用的是MD5+密钥的算法,黑客可以反编译app获取算法

和密钥,然后冒充app发起请求;

 

问题:RSA密钥生成算法是怎样的?

答:

1)随机选取2个足够大的不同素数pq

(最好保证下文的n1024位二进制长度)

2)计算pq的乘积n;

3)计算n的欧拉函数r = (p-1)*(q-1);

4)随机取一个整数e,要求1 < e < r,且er互质;

5)计算e对于n的模反元素d

6)将(n,e)作为公钥,(n,d)作为私钥;(其实可以互换);

7)假设原数据是一个整数m,则加密结果为c=m^e%n;

8)解密过程是c^d%n,可以证明这个结果等于原数据m;

对于任意需要加密的字符串abc,我们可以将每个字母

分开,然后每个字母转成ASCII码,再对每个整数单独加密;

 

这个算法安全性来自于:别人无法根据(n,e)轻易推断出(n,d)

为了推出d,你需要得到r,一种方法是暴力计算,复杂度

很高;另一种方法是先推断pq,这属于大数分解问题,

复杂度也很高;另外,不要忘了,e的选取不是唯一的,

d的值也不是唯一的,这又增加了破解的复杂度;

 

 

 

 

问题:如何生成我们想要的keyStoretrustStore

答:请综合以下几个帖子和文章:

下面的帖子清晰的解释了ssl握手的过程,client预先植入公钥,所以

单验证证书这一步是不需要网络通信的,没有安全隐患;

http://stackoverflow.com/questions/188266/how-are-ssl-certificates-verified

 

下面的帖子清晰的说明了keyStore是什么,证书是什么,trustStore是什么;

Severclient之间是如何建立信任的;

http://stackoverflow.com/questions/2200176/keytool-create-a-trusted-self-signed-certificate

 

下文清晰的解释了首先生成包含公钥私钥对的keyStore

然后从keyStore抽出公钥,看后缀.cert估计这个公钥就证书,

最后用这个证书生成trustStore的过程;

https://developer.jboss.org/wiki/GeneratingSelfSignedCertificateWithKeytool?_sscc=t

 

 

 

问题:一般的认证签名的过程是怎样的?

答案:以google.com为例,

 

通常情况下,认证不是一步完成的,需要好几步,以google.com为例,

我们可以在浏览器看到他的证书,*.google.com是由

Google Internet Authority G2认证的,而G2又是由GeoTrust Global CA认证的,

GeoTrust是知名的根认证组织;浏览器认证这个证书的过程是这样的,

首先这个证书里肯定有G2发给google.com的证书和G2的公钥,

这个证书是用G2的私钥签名的,浏览器用G2的公钥解密这个证书,

如果成功说明这个证书的确是G2发出的,下面,继续认证G2的有效性,

这个证书里肯定还包含GeoTrust发给G2的证书,这个证书是用GeoTrust

的私钥加密的,注意,浏览器预先植入了这些知名根认证组织的公钥,

而不能再使用证书本身包含的公钥了,因为证书里自带的公钥肯能是假的,

于是浏览器用内置的公钥解密这个证书,如果成功,说明这个证书的确是

GeoTrust发给G2的,也就验证了G2的真实身份;

考虑这个情况,如果黑客篡改了证书,把浏览器指向错误的认证路径会怎么样?

那浏览器最后会到达不认识的根认证组织,于是浏览器就会提示用户这个

证书有问题;

 

问题:什么是自认证签名(self-signed)

这是上面情况的一种特例,就是server A的证书是A自己发布的,

并且clientA自己的公钥来认证;我们app需要的就是这种证书,

之所以选择这种证书是因为,不需要拿到其他认证机构去认证,

省时省力省钱,而我们的server只供自己的app访问,

所以只要我们的app认可这个证书就足够了;

 

 

 

问题:我们在解决重复提交问题的时候引入了一个requestCode

这个和token很像啊,他们到底有什么区别?

答:requestCode是客户端生成的,用来标识一次请求意图;

token是服务器生成的,用来标识一个用户的有效登录;

顺便提下,我们原来的防重复提交方案过于复杂,完全可以采用更

简单的方案;所有的请求无外乎add, update, delete,对于add

只需要前端做点防止重复点击的保护就行了,每次点击记录一个

时间,然后在2s之内,禁止用户再次点击,如果用户在间隔很久

之后又点了一下,造成新建了多个订单,这种情况用户完全可以

理解;如果网络超时造成用户误判又点了一下,生成多个订单,

淘宝都有这个问题,用户可以删除多余的订单嘛,也没有多大危害;

对于updatedelete,后台本来就有责任验证状态,服务器永远

都不能相信客户端的数据,只要服务端做了验证,重复提交就不会

造成任何影响了;所以说,requestCode完全是多余的设计!

 

问题:如果server要验证app的身份,则必须在app端存放证书,

App端如何安全的存储私钥?

答:app可以被反编译,理论上总是能被看到,没有什么好办法;

 

问题:如果用了okHttp/AsyncHttpClient等第三方库,怎么使用https

答:这些库对https都有支持,我google过了,有现成的解决方案;

 

 

 

问题:SSL握手过程是怎么样的?

答:见下图

 

问题:SSL为什么使用RSAAES的混合方案?

答:首先如果单纯使用AES,则serverapp是共享一个密钥的,

黑客可以反编译app获得这个密钥,所以这个方案不可行;

其次,RSA算法对被加密的数据有长度要求,假设密钥是128

,则只能加密不超过128位长度的数据,实际的json数据很

可能超过密钥长度;另外,RSA算法相比对称加密算法DES

慢很多;所以单纯使用RSA也不可取;

所以SSL采用了混合方案,动态生成随机的DES密钥,

RSA加密传输DES密钥,之后用这个DES密钥加密数据。

 

 

问题:我们原来设计的token有什么用?用了https还需要

token吗?

答:为了支持单点登录,因为https不关心业务逻辑,所以单点

登录需要我们自己用token实现;用户id只能区分不同的用户,

无法区分不同的设备,另外用户id是永远有效的,没有

“有效期”的概念;所以我们引入了token,一次成功的登录

换取一个token,之后app用这个token去请求其他接口,

直到用在其他设备重新登录,此token失效;

 

问题:https能防止重放攻击吗?

网上说能,具体什么原理还没搞清楚;TODO

请参考 Analysis of the SSL 3.0 protocol

https://www.schneier.com/academic/paperfiles/paper-ssl.pdf

 

问题:说了这么多,具体怎么编程?

答:看了这么多,这篇文章看似最靠谱,代码短小精悍,

作者是squareCTO

Android: Trusting SSL certificates

http://blog.crazybob.org/2010/02/android-trusting-ssl-certificates.html

注意,我看了很多帖子发现,Java默认支持JKS(Java Key Store)证书格式,

Android支持BKS(BouncyCastle Key Store )格式,不支持JKS格式;

下文补充了host verification的部分:
Android: Trusting SSL certificates

http://blog.antoine.li/2010/10/22/android-trusting-ssl-certificates/

 

 

问题:Base64是什么鬼,和加密有什么关系?

答:请自行百度,大概意思是:

现有的网络协议会将不可见字符删除,导致你的数据发生变化,

所以我们需要将数据全部变成可见字符,然后再传输;

Base64的确让数据变的不可读了,但是这个过程是可逆的,

所以不能算加密;

 

问题:总感觉加密和签名有某种搞不清的关系?

答:你的感觉是对的,他们的确有很密切的联系;

首先,RSA算法既能用来加密(用公钥加密,用私钥解密),

也能用来签名(用私钥加密,用公钥解密);

 

问题:这儿谈的签名和apk签名有什么关系?

答:数据签名是为了验证server或者app的身份;

Apk签名是为了验证apk的真实来源;

签名算法是一样的,但是应用的对象不一样;

 

结论:我们担心的问题,https早已给出了解决方案,httpsNetscape

公司在1994年发明的,早就成为业界标准了;

 

 

参考文献:

1) 《改变未来的九大算法》,这本书里有2个章节专门描述了加密和

签名,深入浅出,建议作为入门的第一篇文章读;

 

2https原理:证书传递、验证和数据加密、解密过程解析

http://blog.csdn.net/clh604/article/details/22179907

 

2)Android security - Implementation of Self-signed SSL certificate for your App.

http://www.codeproject.com/Articles/826045/Android-security-Implementation-of-Self-signed-SSL

上文介绍了证书的创建和认证算法

 

4Android 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

 

7One Way and Two Way SSL and TLS

http://www.ossmentor.com/2015/03/one-way-and-two-way-ssl-and-tls.html

 

8HTTPS with Client Certificates on Android

http://chariotsolutions.com/blog/post/https-with-client-certificates-on/

 

9android-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篇好文章:

轻松学习RSA加密算法原理

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

 

12What Is SSL (Secure Sockets Layer) and What Are SSL Certificates?

https://www.digicert.com/ssl.htm

上文章清晰的解释了https链接建立的过程

 

 

13Behind the Scenes of SSL Cryptography

https://www.digicert.com/ssl-cryptography.htm

上文强调了SSL同时使用了对称和非对称加密

 

 

14Analysis of the SSL 3.0 protocol

https://www.schneier.com/academic/paperfiles/paper-ssl.pdf

上文回答了关于SSL防止重放攻击的问题

 

15)两篇系列文章,讲了证书的创建和双向认证;

Android - TLS/SSL Mutual Authentication

http://callistaenterprise.se/blogg/teknik/2011/11/24/android-tlsssl-mutual-authentication/

 

Creating self-signed certificates for use on Android

http://callistaenterprise.se/blogg/teknik/2011/11/24/creating-self-signed-certificates-for-use-on-android/

 

16Generating Self Signed Certificate with Keytool

https://developer.jboss.org/wiki/GeneratingSelfSignedCertificateWithKeytool?_sscc=t

上文介绍了怎么创建自认证的keyStoretrustStore;

 

你可能感兴趣的:(Android网络请求中的安全问题)