OPENSSL与KeyStore

2020年07月12日 阅读数:85
这篇文章主要向大家介绍OPENSSL与KeyStore,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

一、OpenSSL实践

工做中须要配置使用SSL来双向认证并通讯的FTP服务器,以OpenSSL和Java的keytool为例,来完成证书的制做:html

d:/openssl/mkcerts>openssl genrsa -out ca.key 1024java

建立CA私钥
Loading 'screen' into random state - done
warning, not much extra random data, consider using the -rand option
Generating RSA private key, 1024 bit long modulus
...................................................................++++++
.............++++++
e is 65537 (0x10001)
d:/openssl/mkcerts>openssl req -new -days 3650 -x509 -key ca.key -out cacert.pem -config openssl.cnfandroid

建立CA自签名证书(使用上一步建立的CA私钥来签名)
Using configuration from openssl.cnf
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:BEIJING
Locality Name (eg, city) []:BEIJING
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Chelseafc
Organizational Unit Name (eg, section) []:FTPTest
Common Name (eg, YOUR name) []:CHELSEA
Email Address []:chelsea@chelseafc.com
d:/openssl/mkcerts>openssl genrsa -des3 -out server.key 1024git

建立服务器私钥
Loading 'screen' into random state - done
warning, not much extra random data, consider using the -rand option
Generating RSA private key, 1024 bit long modulus
..............++++++
.++++++
e is 65537 (0x10001)
Enter PEM pass phrase:
Verifying password - Enter PEM pass phrase:程序员

d:/openssl/mkcerts>openssl rsa -in server.key -out serverkey.pemweb

加密服务器私钥(保护私钥信息)
read RSA key
Enter PEM pass phrase:
writing RSA keyapache

d:/openssl/mkcerts>openssl req -new -days 3650 -key server.key -out server.csr-config openssl.cnf编程

建立申请服务器所需证书的请求
Using configuration from openssl.cnf
Enter PEM pass phrase:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:BEIJING
Locality Name (eg, city) []:BEIJING
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Chelseafc
Organizational Unit Name (eg, section) []:FTPTest
Common Name (eg, YOUR name) []:CHELSEA
Email Address []:chelsea@chelseafc.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

d:/openssl/mkcerts>openssl ca -days 3650 -keyfile ca.key -cert cacert.pem -outdir . -in server.csr -out server.pem -config openssl.cnfapi

CA签署服务器证书(须要CA私钥和序列号文件demoCA/serial, demoCA/index.txt)
Using configuration from openssl.cnf
Loading 'screen' into random state - done
Check that the request matches the signature
Signature ok
The Subjects Distinguished Name is as follows
countryName :PRINTABLE:'CN'
stateOrProvinceName :PRINTABLE:'BEIJING'
localityName :PRINTABLE:'BEIJING'
organizationName :PRINTABLE:'Chelseafc'
organizationalUnitName:PRINTABLE:'FTPTest'
commonName :PRINTABLE:'CHELSEA'
emailAddress :IA5STRING:'chelsea@chelseafc.com'
Certificate is to be certified until Oct 26 03:01:33 2006 GMT (365 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

d:/openssl/mkcerts>openssl x509 -in server.pem -out server.crt

转换格式
数组

d:/openssl/mkcerts>openssl x509 -in demoCA/cacert.pem -out demoCA/cacert.crt

转换格式

d:/openssl/mkcerts>keytool -genkey -keyalg RSA -alias ftpsconnector -keystore ftps.jks -storepass changeit -storetype jks

产生Java客户端私钥文件
您的名字与姓氏是什么?
[Unknown]: CHELSEA
您的组织单位名称是什么?
[Unknown]: FTPTest
您的组织名称是什么?
[Unknown]: Chelseafc
您所在的城市或区域名称是什么?
[Unknown]: BEIJING
您所在的州或省份名称是什么?
[Unknown]: BEIJING
该单位的两字母国家代码是什么
[Unknown]: CN
CN=CHELSEA, OU=FTPTest, O=Chelseafc, L=BEIJING, ST=BEIJING, C=CN 正确吗?
[否]: Y

输入<ftpsconnector>的主密码
(若是和 keystore 密码相同,按回车):

d:/openssl/mkcerts>keytool -certreq -alias ftpsconnector -keyalg RSA -file ftpsconnector.csr -keystore ftps.jks

产生Java客户端证书请求
输入keystore密码: changeit

d:/openssl/mkcerts>openssl ca -days 3650 -keyfile ca.key -cert cacert.pem -outdir . -in ftpsconnector.csr -out ftpsconnector.pem -config openssl.cnf

CA签署Java客户端证书
Using configuration from openssl.cnf
Loading 'screen' into random state - done
Check that the request matches the signature
Signature ok
The Subjects Distinguished Name is as follows
countryName :PRINTABLE:'CN'
stateOrProvinceName :PRINTABLE:'BEIJING'
localityName :PRINTABLE:'BEIJING'
organizationName :PRINTABLE:'Chelseafc'
organizationalUnitName:PRINTABLE:'FTPTest'
commonName :PRINTABLE:'CHELSEA'
Certificate is to be certified until Oct 26 03:05:08 2006 GMT (365 days)
Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

d:/openssl/mkcerts>openssl x509 -in ftpsconnector.pem -out ftpsconnector.cer

转换格式

d:/openssl/mkcerts>keytool -import -alias root -trustcacerts -file demoCA/cacert.crt -keystore ftps.jks

导入CA证书到jks文件并信任之(由此CA所签署的全部证书也所以在信任之列)

输入keystore密码: changeit
Owner: EMAILADDRESS=chelsea@chelseafc.com, CN=CHELSEA, OU=FTPTest, O=Chelseafc, L=BEIJING, S
T=BEIJING, C=CN
发照者: EMAILADDRESS=chelsea@chelseafc.com, CN=CHELSEA, OU=FTPTest, O=Chelseafc, L=BEIJING,
ST=BEIJING, C=CN
序号: 0
有效期间: Wed Oct 26 10:55:43 CST 2005 至: Sat Oct 24 10:55:43 CST 2015
认证指纹:
MD5: 85:21:11:10:26:4A:CD:01:55:B7:47:DF:0D:58:AA:A3
SHA1: 91:74:88:03:B7:5C:E4:BD:27:1F:27:BF:10:23:0A:BA:2C:42:13:2B
信任这个认证? [否]: y
认证已添加至keystore中

d:/openssl/mkcerts>keytool -import -alias ftpsconnector -trustcacerts -file ftpsconnector.cer -keystore ftps.jks

导入本身的证书到jks文件(至此,此jks文件包括了创建SSL链接所需全部信息)
输入keystore密码: changeit
认证回复已安装在 keystore中

其它OpenSSL命令举例

openssl pkcs12 -export -clcerts -in client.pem -inkey clientkey.pem -out client.p12

openssl pkcs8 -inform PEM -nocrypt -in abcwebnet-pkcs8.key -out abcwebnet.key 

openssl pkcs12 -export -out abcwebnet.pfx -inkey abcwebnet.key -in abcwebnet-pem.crt

... ...

 

二、keytool实践

keystore这个名字其实有点误导,应该是CertStore,能够同时包含两种信息:本身的keyEntry,和trusted cert entry.(天然包括本身的私钥公钥和信任的公钥了)(有时会分开,信任的证书存储在单独的文件中)

keystore能够有两类密码,一个是保护这个文件的(storepass),一种是保护文件里每个key的(keypass)

能够为每一个key指定alias,而后使用alias来引用或访问对应的key

Example:


rem 建立客户端keystore

keytool -genkey -keyalg RSA -keystore client.jks -storetype jks -storepass client -alias client_rsa -keypass client_rsa -dname "CN=Client, OU=IBM, C=US" -keysize 1024 -validity 1460


rem 建立服务端keystore 

keytool -genkey -keyalg RSA -keystore server.jks -storetype jks -storepass server -alias server_rsa -keypass server_rsa -dname "CN=Server, OU=IBM, C=US" -keysize 1024 -validity 1460


rem 从客户端keystore中导出通用格式的证书,以备导入到服务端keystore

keytool -export -keystore client.jks -storetype jks -storepass client -alias client_rsa -file client_rsa.cer


rem 从服务端keystore中导出通用格式的证书,以备导入到客户端keystore

keytool -export -keystore server.jks -storetype jks -storepass server -alias server_rsa -file server_rsa.cer


rem 导入客户端证书到服务端keystore(此动做的后果是使服务端信任客户端)

keytool -import -noprompt -keystore server.jks -storetype jks -storepass server -alias client_rsa -file client_rsa.cer


rem 导入服务端证书到客户端keystore(此动做的后果是使客户端信任服务端)

keytool -import -noprompt -keystore client.jks -storetype jks -storepass client -alias server_rsa -file server_rsa.cer


rem 列出客户端keystore包含的信息供查看

keytool -list -keystore client.jks -storepass client -v

rem 列出服务端keystore包含的信息供查看

keytool -list -keystore server.jks -storepass server -v

 

三、Java客户端

客户端一般有一个文件,包含了全部信任的证书信息(包括SSL服务器),如上面的ftps.jks,能够以编程的方式将此文件的位置密码格式等告知客户端socket运行时,这样在试图创建SSL链接时收到服务器发送过来的证书时,即可以进行信任验证

能够经过java.security file in jdk folder 或者 -Djavax.net.ssl.keyStore=xxx -Djavax.net.ssl.keyStorePassword=yyy 来设置

能够参考: http://www-128.ibm.com/developerworks/cn/websphere/techjournal/0502_benantar/0502_benantar.html


为你的安卓应用实现自签名的 SSL 证书


介绍

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

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

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

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

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

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

Boobs
Boobs
翻译于 1个月前

2人顶

 翻译的不错哦!

背景

从最基本的开始讲.

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

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

?
1
2
3
URL urlConnection =  new  URL( "http://www.codeproject.com/" );
 
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

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

Boobs
Boobs
翻译于 1个月前

1人顶

 翻译的不错哦!

HTTPS是什么?

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

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

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

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

像下列代码这样打开一个 https 链接, 能够保障这个链接的数据通信安全.

?
1
2
3
4
5
URL urlConnection =  new  URL( "https://www.codeproject.com/" );
 
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
 
InputStream in =  new  BufferedInputStream(urlConnection.getInputStream());

HTTPS 经过 SSL/TLS 传递数据.

Boobs
Boobs
翻译于 1个月前

2人顶

 翻译的不错哦!

SSL/TLS:

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

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

Boobs
Boobs
翻译于 1个月前

1人顶

 翻译的不错哦!

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等).

Boobs
Boobs
翻译于 1个月前

1人顶

 翻译的不错哦!

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

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

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

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

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

Boobs
Boobs
翻译于 1个月前

1人顶

 翻译的不错哦!

TLS (SSL)中的加密

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

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

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

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

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

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

Boobs
Boobs
翻译于 1个月前

1人顶

 翻译的不错哦!

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 链接

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


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

可是若是你连的服务器用的是本身颁发的证书(self-singed certificate), 那就会出现错误.

Boobs
Boobs
翻译于 1个月前

1人顶

 翻译的不错哦!

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

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

SSL 证书大体分三类:

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

  • 没有获得安卓承认的证书颁发机构颁发的证书.

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

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

Boobs
Boobs
翻译于 1个月前

1人顶

 翻译的不错哦!

为何有人喜欢用自签名证书 

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

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

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

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

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

我的觉得, 在手机应用中使用自签名证书没什么很差, 既不须要花钱, 也不须要修改代码.(注:若是你用的是机构颁发的证书, 在产品发布阶段, 须要修改代码).

Boobs
Boobs
翻译于 1个月前

1人顶

 翻译的不错哦!

其它翻译版本(1)

可是下面的戏法的通常性的https代码

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

若是你使用上述的代代码去验证你的本身签署的证书,因为在android操做系统中本身签署的不能经过验证的,因此安卓应用软件将会抛出错误。所以你须要书写你本身的代码来检查你的本身签署的证书。

可是在这个领域中,安卓开发者犯了一个很大的错误,本身签署的证书在web开发中不是常见的,同时大多数安卓开发者来自于web开发者,因此开发者缺失在密码学的概念的知识。

在我分析中,我发现开发者仅仅是简单的复制、粘贴Stack Overflow和其余博客中容许你的应用默认信任因此证书的答案。即便大多说的答案表述仅仅在测试模式下可使用,可是开发者简单地复制代码,将会致使应用软件在遭到中间件攻击和session黑客攻击是,表现的很是的脆弱!

例子:

http://stackoverflow.com/questions/2703161/how-to-ignore-ssl-certificate-errors-in-apache-httpclient-4-0

http://stackoverflow.com/questions/2012497/accepting-a-certificate-for-https-on-android?lq=1

http://www.caphal.com/android/using-self-signed-certificates-in-android/#toc_3

http://stackoverflow.com/questions/2642777/trusting-all-certificates-using-httpclient-over-https

洪丹阳1991
洪丹阳1991
翻译于 1个月前

0人顶

 翻译的不错哦!

在使用本身签署的证书时通常性的错误

信任因此的证书

TrustManager的主要责任是去决定提出的认证证书应该是可信任的。若是证书是不可信任的,那么链接将会被终止。去认证远程的安全套接字识别,你须要用一个或者多个TrustManager(s)初始化SSLContext对象。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import  org.apache.http.conn.ssl.SSLSocketFactory;
public  class  MySSLSocketFactory  extends  SSLSocketFactory {
     SSLContext sslContext = SSLContext.getInstance( "TLS" );
 
     public  MySSLSocketFactory(KeyStore truststore)  throws  NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
         super (truststore);
 
         TrustManager tm =  new  X509TrustManager() {
             public  void  checkClientTrusted(X509Certificate[] chain, String authType)  throws  CertificateException {
             }
 
             public  void  checkServerTrusted(X509Certificate[] chain, String authType)  throws  CertificateException {
             }
 
             public  X509Certificate[] getAcceptedIssuers() {
                 return  null ;
             }
         };
 
         sslContext.init( null new  TrustManager[] { tm },  null );
    }
 
     @Override
     public  Socket createSocket(Socket socket, String host,  int  port,  boolean  autoClose)  throws  IOException, UnknownHostException {
         return  sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
     }
 
     @Override
     public  Socket createSocket()  throws  IOException {
         return  sslContext.getSocketFactory().createSocket();
     }
}

我发现,80到100个应用软件中,在20到25个应用中实现了上述的代码。

洪丹阳1991
洪丹阳1991
翻译于 1个月前

0人顶

 翻译的不错哦!

在上述的TrustManager接口中,能够实现信任因此的证书,不管是谁签署的或者即便他们发布的任何主题。这个接口将会容许接受ANY证书。接受任何的证书将会危害数据的完整性、安全性等等。

在上述的例子中,检查客户端可信任性,得到接受事件,检查服务器端可信任性是三点重要的功能。每一位开发者都应该留意这三点功能的实现上。可是却不多有开发者从不一样的网站中搜索、负责上述的功能。

洪丹阳1991
洪丹阳1991
翻译于 1个月前

0人顶

 翻译的不错哦!

容许全部的主机名。

忘记检查证书是否在这个地址发布是有可能的。当证书接受了example.com的服务器,那么另外的一个域名也将被接受。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
 
DefaultHttpClient client =  new  DefaultHttpClient();
 
SchemeRegistry registry =  new  SchemeRegistry();
SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();
socketFactory.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
registry.register( new  Scheme( "https" , socketFactory,  443 ));
SingleClientConnManager mgr =  new  SingleClientConnManager(client.getParams(), registry);
DefaultHttpClient httpClient =  new  DefaultHttpClient(mgr, client.getParams());
 
// Set verifier     
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
 
// Example send http request
final  String url = "https: //www.paypal.com&rdquo;
HttpPost httpPost =  new  HttpPost(url);
HttpResponse response = httpClient.execute(httpPost);
 
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
?
1
HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;

上述的代码中,即便是错误的实现,也将会接受对任何域名的任何CA证书声明。

洪丹阳1991
洪丹阳1991
翻译于 1个月前

0人顶

 翻译的不错哦!

Mixed-Mode/No SSL.

应用软件开发者在相同的应用中使用最大安全、不安全的链接,或者不使用SSL将是免费的。这不是直接的SSL声明,可是和提到的没有向外的签署个有关,同时对于通常软件的使用者,检查是否使用一个安全的链接是不可能的。这将会为例如SSL剥离,或者像FireSheep这样的攻击开后门。

SSL剥离是另外的一种可使MITMA登录并抵制SSL链接方式。利用使用最大HTTP和HTTPS应用。SSL剥离依赖大量创建在点击连接、或者来自于没有SSL重定向保护的网站SSL链接。在SSL剥离中,Mallory用HTTPS://取代了没有保护的网站中http:// 连接中。所以,除非使用者注意到了连接被篡改了,Mallory能够彻底地规避SSL保护。这样的攻击主要与浏览器应用、或者原生使用安卓WebView应用有关。

更多关于SSL剥离的信息:

http://security.stackexchange.com/questions/41988/how-does-sslstrip-work

http://www.thoughtcrime.org/software/sslstrip/


洪丹阳1991
洪丹阳1991
翻译于 1个月前

0人顶

 翻译的不错哦!

证书锁定

直接在代码中固定写死使用某个服务器的证书. 而后在应用中使用本身定义的信任存储(trust store)代替手机系统自带的那个, 去链接指定的服务器.

这样作的好处是, 咱们既能使用自签名证书, 又不须要额外安装其余证书.

优点

  • 安全性提高 - 采用这种方式, 应用再也不依赖系统自带的信任存储(trust store). 使得破解这种应用变得复杂: 首先你要反编译, 修改完后, 还要从新编译.  关键是你不可能使用应用做者原先用的那个 keystore 文件从新颁发证书.

  • 成本下降 - 证书锁定方式让咱们能够在本身的服务器上使用免费的自签名证书,  调用本身写的 API. 虽然说复杂了点, 但是像这种既不花钱, 还能提升应用安全的好事上哪找去?

Boobs
Boobs
翻译于 1个月前

0人顶

 翻译的不错哦!

缺点

  • 适应性较差 - 一旦 SSL 证书出现变更, 应用也要跟着升级. 再发布到 Google Play. 而后祈祷用户能都升级到最新版本.

安卓的 SSLContext 自带的 TrustManager 没法让本文示例中提到的自签名证书经过验证. 解决的办法是本身定义一个 TrustManager 类. 而后用这个类去验证自签名证书. 

先把证书加载到 KeyStore, 而后用 KeyStore 生成一个 TrustManager 数组, 最后再用这个 TrustManager 数组建立 SSLContext.

本文的应用把服务器的证书直接存进应用的资源.(毕竟这个文件是全部用户都共用的, 并且也不会常常改动), 固然你能够把它存到别的地方.

Boobs
Boobs
翻译于 1个月前

0人顶

 翻译的不错哦!

实现的步骤

第1步: 建立自签名证书和.bks 文件

1) 

建立 BKS 或者 keystore, 须要用到下面这个文件,bcprov-jdk15on-146.jar, 版本不少, 我用的是这个:http://www.bouncycastle.org/download/bcprov-jdk15on-146.jar, 下载后, 把文件存到 C:\codeproject.

而后用 Keytool 生成 keystore 文件.(keytool 是 Java SDK 自带的文件, 跟javac 放在同一个目录下)在命令提示符窗口中输入 keytool 就能看到这个工具的各类选项说明. 或者输入下列路径运行.

"C:\Program Files (x86)\Java\jre7\bin>keytool".

Boobs
Boobs
翻译于 1个月前

0人顶

 翻译的不错哦!

2)

下面是用 keytool 生成 keysotre 文件的命令.  要是这个文件已经存在, 这一步能够忽略.

keytool -genkey -alias codeproject -keystore C:\codeproject\codeprojectssl.keystore -validity 365

这行命令建立一个别名为 code project 的密钥(key), 生成的文件名是 codeprojectssl.keystore. 执行文件生成过程当中会要求输入密钥(key)跟keystore的密码诸如此类的东东. 这里须要注意下, 当要求你录入 Common name 的时候, 要填你的主机名. 本文例子用的是: codeproject.com

3)

keytool -export -alias codeproject -keystore C:\codeproject\codeprojectssl.keystore -file C:\codeproject\codeprojectsslcert.cer

这行命令将密钥(key)从 .keystore 文件导入 .cer 文件.

Boobs
Boobs
翻译于 1个月前

0人顶

 翻译的不错哦!

4) 

keytool -import -alias codeproject -file C:\codeproject\codeprojectsslcert.cer -keystore C:\codeproject\codeprojectssl.bks -storetype BKS -providerClass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath C:\codeproject\bcprov-jdk15on-146.jar

搞定! 如今, 所有 .bks 文件都生成了. 稍后将这些文件复制到安卓应用中. 链接那些使用自签名证书的服务器的时候会用到.

第2步

把 .keystore 文件复制到 /androidappdir/res/raw/

第3步

建立一个新类: MyHttpClient,  继承 DefaultHttpClient 类. 这个新类在验证SSL 证书的时候, 会自动加载咱们本身建立的 keystore 文件, 而不是安卓自带的那个. 只要证书跟服务器匹配上了就没问题. 代码以下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import  java.io.InputStream;
import  java.security.KeyStore;
 
import  android.content.Context;
 
public  class  MyHttpClient  extends  DefaultHttpClient {
   
  private  static  Context context;
  
  public  static  void  setContext(Context context) {
   MyHttpClient.context = context;
  }
 
  public  MyHttpClient(HttpParams params) {
   super (params);
  }
 
  public  MyHttpClient(ClientConnectionManager httpConnectionManager, HttpParams params) {
   super (httpConnectionManager, params);
  }
 
  @Override
     protected  ClientConnectionManager createClientConnectionManager() {
         SchemeRegistry registry =  new  SchemeRegistry();
         registry.register( new  Scheme( "http" , PlainSocketFactory.getSocketFactory(),  80 ));
         
         // 用咱们本身定义的 SSLSocketFactory 在 ConnectionManager 中注册一个 443 端口  
         registry.register( new  Scheme( "https" , newSslSocketFactory(),  443 ));
         return  new  SingleClientConnManager(getParams(), registry);
     }
  
     private  SSLSocketFactory newSslSocketFactory() {
         try  {
             // Get an instance of the Bouncy Castle KeyStore format
             KeyStore trusted = KeyStore.getInstance( "BKS" );
             // 从资源文件中读取你本身建立的那个包含证书的 keystore 文件
             
             InputStream in = MyHttpClient.context.getResources().openRawResource(R.raw.codeprojectssl);  //这个参数改为你的 keystore 文件名
             try  {
                 // 用 keystore 的密码跟证书初始化 trusted                            
                 trusted.load(in,  "这里是你的 keystore 密码" .toCharArray());
             finally  {
                 in.close();
             }
             // Pass the keystore to the SSLSocketFactory. The factory is responsible
             // for the verification of the server certificate.
             SSLSocketFactory sf =  new  SSLSocketFactory(trusted);
             // Hostname verification from certificate
             // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
             sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);  // 这个参数能够根据须要调整, 若是对主机名的验证不须要那么严谨, 能够将这个严谨程度调低些.
             return  sf;
         catch  (Exception e) {
             throw  new  AssertionError(e);
         }
     }
}

MyHttpClient 类的调用代码以下:

?
1
2
3
4
5
6
// Instantiate the custom HttpClient
DefaultHttpClient client =  new  MyHttpClient(getApplicationContext());
HttpGet get =  new  HttpGet( "https://www.google.com" );
// 以 GET 方式读取服务器返回的数据
HttpResponse getResponse = client.execute(get);
HttpEntity responseEntity = getResponse.getEntity();

这是我在 CodeProject 上的发布的处女做.

祝你们开心编程, 安全第一