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

oschina 推荐于 2年前 (共 20 段, 翻译完成于 10-07) 评论 11
收藏  
144
推荐标签: Android 待读

介绍

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

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

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

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

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

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

BreakingBad
 翻译得不错哦!

背景

从最基本的开始讲.

阅读本文前, 最好先看下 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
 翻译得不错哦!

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
 翻译得不错哦!

SSL/TLS:

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

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

BreakingBad
 翻译得不错哦!

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
 翻译得不错哦!

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

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

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

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

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

BreakingBad
 翻译得不错哦!

TLS (SSL)中的加密

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

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

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

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

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

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

BreakingBad
 翻译得不错哦!

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
 翻译得不错哦!

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

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

SSL 证书大致分三类:

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

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

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

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

BreakingBad
 翻译得不错哦!

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

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

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

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

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

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

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

BreakingBad
 翻译得不错哦!
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们
评论(11)
Ctrl/CMD+Enter

写得不错
发现osc发的文章翻译实在惨不忍睹。
为什么t宝有6块的ssl证书?
keytool -genkey -alias codeproject -keystore C:\codeproject\codeprojectssl.keystore -validity 365
根本没有 -genkey 这个选项啊,而且我用了 -genkeypair后 也没有找到哪里可以输入 common name
服务端验证的代码怎么写?有没有大神出来补充一下啊。

引用来自“loyal”的评论

为什么t宝有6块的ssl证书?
那都是chmodo 的证书,买其他东西带的。

引用来自“loyal”的评论

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

引用来自“kslr”的评论

那都是chmodo 的证书,买其他东西带的。
哦?买什么会带那个...有什么区别?解释解释学习学习
PHP服务端验证的代码怎么写?有没有哪位大神或者大侠出来补充一下,私聊我,有报酬
The constructor MyHttpClient(Context) is undefined,我在mainactivity调用,报如上错误错误
DefaultHttpClient client = new MyHttpClient(getApplicationContext());这段代码报的错
/androidappdir/ 什么目录啊
顶部