为你的安卓应用实现自签名的 SSL 证书 已翻译 100%

oschina 投递于 2014/10/06 07:01 (共 20 段, 翻译完成于 10-07)
阅读 18703
收藏 145
7
加载中

介绍

网络安全已成为大家最关心的问题. 如果你利用服务器存储客户资料, 那你应该考虑使用 SSL 加密客户跟服务器之间的通讯. 随着这几年手机应用迅速崛起. 黑客也开始向手机应用转移, 原因有下列3点:

  1. 手机系统各式各样, 缺乏统一的标准.

  2. 许多程序员缺乏手机应用开发经验.

  3. 更严重的是, 通过手机应用, 黑客可以得到手机用户的隐私数据, 如:日程安排, 联系人信息, 网页浏览历史记录, 个人资料, 社交数据, 短信或者手机用户所在的地理位置.

最为一个网络安全爱好者的我, 最近花了几个月的时间对50到60安卓应用进行安全分析, 结果发现这些应用存在许多安全漏洞.

下面我主要讲一讲, 怎样才能写出比较安全的安卓代码.

BreakingBad
BreakingBad
翻译于 2014/10/06 09:47
5

背景

从最基本的开始讲.

阅读本文前, 最好先看下 Ranjan.D article 写的一篇跟安卓连接有关的文章:(http://www.codeproject.com/Articles/818734/Article-Android-Connectivity).

 下列代码用来打开一个 http 连接.

URL urlConnection = new URL("http://www.codeproject.com/");

HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

不要在 http连接中打开:登陆页面, 或是传递用户名, 密码, 银行卡之类的重要个人资料. 这些重要个人数据应该通过 HTTPS 传输. (具体参看HTTPS).

BreakingBad
BreakingBad
翻译于 2014/10/06 10:00
2

HTTPS是什么?

HTTPS 其实就是个安全版的 http. HTTPS 能保证电子商务的交易安全. 如:网上银行.

像 IE 或者火狐浏览器, 如果出现下面的挂锁图标.

同时, 在浏览器的地址栏中以 https:// 开头, 这表示, 你的浏览器跟这个网站的数据往来都是安全的.

https 跟 http 的最大区别在于 https 多加了一个保障通讯安全的层.

像下列代码这样打开一个 https 连接, 可以保障这个连接的数据通讯安全.

URL urlConnection = new URL("https://www.codeproject.com/");

HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();

InputStream in = new BufferedInputStream(urlConnection.getInputStream());

HTTPS 通过 SSL/TLS 传递数据.

BreakingBad
BreakingBad
翻译于 2014/10/06 10:19
3

SSL/TLS:

SSL (Secure Sockets Layer) 是一种在客户端跟服务器端建立一个加密连接的安全标准. 一般用来加密网络服务器跟浏览器, 或者是邮件服务器跟邮件客户端(如: Outlook)之间传输的数据.

SSL 能保障敏感信息(如:银行卡号, 社保卡号, 登陆凭证等)的传输安全. 一般情况下, 数据在浏览器跟服务器之间的传输使用的是明文格式, 这种方式存在资料被窃取的风险. 如果黑客能拦截浏览器跟服务器之间的通讯数据, 就能看到通讯的内容. 

BreakingBad
BreakingBad
翻译于 2014/10/06 10:38
2

SSL/HTTPS and X.509 证书概述

你要是对 SSL 或 X.509 证书一无所知, 那我大概解释下. 对于那些打算用自签名证书(self-signed certificate)的人来说, 需要了解自签名证书跟花钱购买机构颁发的证书有什么区别. 

首先我们需要了解下 SSL 证书究竟是个什么东东? 其实它就包含俩部分: 1) 一个身份标识, 一个用来识别身份的东西, 有点类似警察叔叔通过护照或驾照查你的身份; 2) 一个公共密钥, 这个用来给数据加密, 而且只有证书的持有者才能解密. 简而言之, SSL 证书就俩个功能, 身份验证跟保障通讯过程中的数据安全.

另外还有一点很重要. 那就是一个证书可以给另外一个证书“签字”. 用 layman 的话说就是 Bob 用他自己的证书在别的证书上盖上 “同意” 两个红红的大字. 如果你信任 Bob (当然还有他的证书), 那么你也可以信任由他签发的证书. 在这个例子中, Bob 摇身一变, 成了证书颁发机构(Certificate Authority). 现在主流的浏览器都自带一大堆受信任证书颁发机构(trusted Certificate Authorities)(比如:ThawteVerisign等).

BreakingBad
BreakingBad
翻译于 2014/10/06 16:46
2

最后我们讲一讲浏览器是怎么使用证书的. 笼统的讲, 当你打开下列连接的时候 “https://www.yoursite.com” :

  1. 服务器会给浏览器发一个证书.

  2. 浏览器会对比证书中的“common name”(有时也叫 “subject”) 跟服务器的域名是否一样. 例如, 一个从“www.yoursite.com” 网站发过来的证书就应该有一个内容是 “www.yoursite.com” 的 common name, 否则浏览器就会提示该证书有问题.

  3. 浏览器验证证书真伪, 有点像门卫通过证件上的全息图辨别你的证件是不是真的.  既然在现实生活中有人伪造别人的身份. 那么在网络世界也就有人造假, 比如用你的域名“www.yoursite.com” 来伪造一个安全证书.  浏览器在验证的时候, 会检查这个证书是否是它信任机构颁发的, 如果不是, 那么浏览器就会提示这个证书可能有问题. 当然, 用户可以选择无视警告, 继续使用.

  4. 一旦证书通过验证 (或是用户无视警告, 继续使用有问题的证书), 浏览器就开始利用证书中的公开密钥加密数据并传给服务器.

BreakingBad
BreakingBad
翻译于 2014/10/06 11:26
2

TLS (SSL)中的加密

一旦服务器发过来的证书通过验证, 浏览器就会利用证书中包含的公共密钥加密某个指定的共享密钥, 然后发给服务器. 这个加密过的共享密钥只能用服务器的私有密钥才能解密(非对称加密), 别人无法解密出其中的内容. 服务器把解密出来的共享密钥保存起来, 供本次连接会话专用. 从现在开始, 服务器跟浏览器之间的所有通讯信息都用这个共享密钥加密解密(对称加密).

理论部分就这么多, 下面我们来看几个例子.

在浏览器中打开网站 mail.live.com , 地址栏中会出现一个绿色图标, http 也会变成 https.

单击这个绿色图标, 然后点证书信息连接, 就能看到下列内容.

这是个 SSL 证书, 该证书是 Verisign 给 mail.live.cm 颁发的.

Verisign 是一个证书颁发机构, 它提示你的浏览器正在连接的网站是: mail.live.com, 需要跟这个网站的服务器建立一条安全连接进行通讯, 避免他人拦截或篡改浏览器跟服务器之间传递的数据.

BreakingBad
BreakingBad
翻译于 2014/10/06 12:03
2

MITM 攻击

MITM 攻击(MITMA)是指: 黑客拦截篡改网络中的通讯数据

被动 MITMA 是指黑客只能窃取通讯数据, 而在主动 MITMA 中, 黑客除了窃取数据, 还能篡改通讯数据. 黑客利用 MITMA 方式攻击手机要比攻击台式电脑容易的多. 这主要是因为使用手机的环境在不固定, 有些地方用手机连接上网并不安全, 尤其是那些对公众免费开放的无线网络热点.

证书颁发机构(CA)

·Symantec (which bought VeriSign's SSL interests and owns Thawte and Geotrust) 38.1% 市场份额

·Comodo SSL 29.1%

·Go Daddy 13.4%

·GlobalSign 10%

Jelly bean 版本的安卓系统中, 你可以在下列路径中找到证书颁发机构:

设置 -> 安全 -> 受信任的凭证.

Https 连接

URL url = new URL("https://www.example.com/");   
HttpsURLConnection urlConnection = (HttpsURLConnection)url.openConnection();   
InputStream in = urlConnection.getInputStream();


如果你连接的服务器(www.example.com)传过来的证书是由机构颁发的, 这段代码就能正常运行.

但是如果你连的服务器用的是自己颁发的证书(self-singed certificate), 那就会出现错误.

BreakingBad
BreakingBad
翻译于 2014/10/06 12:31
3

什么是自签名证书( self-signed certicates)

自签名证书就是没有通过受信任的证书颁发机构, 自己给自己颁发的证书.

SSL 证书大致分三类:

  • 由安卓认可的证书颁发机构(如: VeriSign), 或这些机构的下属机构颁发的证书.

  • 没有得到安卓认可的证书颁发机构颁发的证书.

  • 自己颁发的证书, 分临时性的(在开发阶段使用)或在发布的产品中永久性使用的两种.

只有第一种, 也就是那些被安卓系统认可的机构颁发的证书, 在使用过程中不会出现安全提示.

BreakingBad
BreakingBad
翻译于 2014/10/06 12:52
3

为什么有人喜欢用自签名证书 

  1. 免费. 购买受信任机构颁发的证书每年要交 100 到 500 美元不等的费用. 自签名证书不花一分钱.

  2. 自签名证书在手机应用中的普及率较高 (跟用电脑浏览网页不同, 手机的应用一般就固定连一台服务器.).

  3. 在开发阶段写的代码,  测试跟发布的时候也可以用.

最近一项调查表明, 810万个证书中, 只有 320万个是由受信任机构颁发的. 剩余490万证书中, 自签名的占48%, 未知机构颁发的占33%, 而不被信任的机构颁发的证书占19%.

无独有偶, 我的分析结果也表明, 起码有 60% 安卓应用使用自签证书.

个人以为, 在手机应用中使用自签名证书没什么不好, 既不需要花钱, 也不需要修改代码.(注:如果你用的是机构颁发的证书, 在产品发布阶段, 需要修改代码).

BreakingBad
BreakingBad
翻译于 2014/10/06 13:14
3
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(11)

l
lx9755
/androidappdir/ 什么目录啊
sky_fly
sky_fly
DefaultHttpClient client = new MyHttpClient(getApplicationContext());这段代码报的错
sky_fly
sky_fly
The constructor MyHttpClient(Context) is undefined,我在mainactivity调用,报如上错误错误
aam
aam
PHP服务端验证的代码怎么写?有没有哪位大神或者大侠出来补充一下,私聊我,有报酬
loyal
loyal

引用来自“loyal”的评论

为什么t宝有6块的ssl证书?

引用来自“kslr”的评论

那都是chmodo 的证书,买其他东西带的。
哦?买什么会带那个...有什么区别?解释解释学习学习
kslr
kslr

引用来自“loyal”的评论

为什么t宝有6块的ssl证书?
那都是chmodo 的证书,买其他东西带的。
旅行中的狗
旅行中的狗
服务端验证的代码怎么写?有没有大神出来补充一下啊。
旅行中的狗
旅行中的狗
keytool -genkey -alias codeproject -keystore C:\codeproject\codeprojectssl.keystore -validity 365
根本没有 -genkey 这个选项啊,而且我用了 -genkeypair后 也没有找到哪里可以输入 common name
loyal
loyal
为什么t宝有6块的ssl证书?
uwunmn
uwunmn
发现osc发的文章翻译实在惨不忍睹。
返回顶部
顶部