Android开发中的加密和签名问题

声明:每个字都是自己敲的,绝对有干货,还没时间排版,抱歉;


加密和签名

 

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

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

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

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

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

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

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

会不会被堵死?

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

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

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

可信的app,咋办?

 

 

怎么解决?

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

就看不到真实数据了;

 

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

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

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

 

针对问题3,引入图片验证码和token机制,登录的时候

要求用户在app输入图片验证码,登录后服务器返回

一个动态生成的tokenapp,之后app的所有请求必须

携带这个token;当服务器遇到来自这个token的频繁的

重复请求的时候,立即让这个token失效,拒绝来自这个

token的后续所有请求,同时让app退出登录,

要求用户重新做一次登录操作;

(疑问:为什么微信支付宝没有这个机制?体验不好?)

 

解决方法2:时间戳+token方案;每个请求带一个时间戳,

这个时间戳和其他数据绑在一起并统一加密,所以黑客

无法单独修改时间戳,如果服务器遇到来自同一个token

相同时间戳的请求,即可断定这是一次重放攻击,让token失效;

(疑问:如果支持多点登录,则2台手机上app理论上有可能

发起相同时间戳的请求,服务器会误杀吗?

解决办法:2个手机上的app使用独立的token,但是登录

的时候除了用户名密码还需要传设备信息用来区分不同手机咯)

 

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

检查,这样就没事了;

 

理论:

建议参考《改变未来的九大算法》,通俗易懂;

 

密钥生成算法:

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码,再对每个整数单独加密;

从上文的分析,你也能发现,rsa加密过程比较费时,

一种改进策略是用对称加密算法加密数据,这个算法比较快,

然后将这个对称密钥本身用rsa非对称密钥加密;

 

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

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

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

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

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

 

注:要想真的理解以上算法,建议多读几篇参考文献;

 

细节:

1)加密

考虑app请求服务器的场景;

appserver的公钥加密数据;

Serverserver的私钥解密数据;由于只要server知道

自己的私钥,所以黑客无法破解数据;

 

反过来,考虑服务器给app返回数据的场景;

serverapp的公钥加密数据;

App用自己的私钥解密数据;由于只有app知道自己的

私钥,所以黑客无法破解数据;

(疑问:app的私钥如何保存?

 

2)签名

还是考虑app请求服务器的场景;(反过来的情况类似)

Appapp的私钥加密数据,然后将加密后的数据连同

原数据传给服务器;

Serverapp的公钥解密数据,如果得到的数据和原数据

相同,则证明这个数据的确来自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) 《改变未来的九大算法》

 

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

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

 

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

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值