您的位置:首页 > 理论基础 > 计算机网络

HTTPS和Android

2016-03-30 17:40 543 查看
一.非对称加密和对称加密

在HTTPS中使用了非对称加密技术和对称加密。非对称加密的好处是私钥和公钥分离,公钥加密,私钥解密,向外只暴露公钥。所以即使得到了公钥也无法解密。缺点是效率低下;

非对称加密(RSA):

其中公钥和私钥都可以用来加密和解密E(D(stuff))=D(E(stuff))=stuff

公钥作为证书会返回给浏览器,公钥加密,私钥解密用作加密系统。

私钥保存在服务器端,私钥加密,公钥解密用作签名系统。



   图一 加密系统



图二 数字签名系统

对称加密的特点是公钥私钥一致,好处是效率高;缺点是不安全,公钥暴露后信息就可以被解密了。

在HTTPS握手过程中,浏览器获得公钥后生成一个加密的随机数返回给服务器,这个随机数只能用服务器的私钥才能解密,所以保证了随机数的安全性。

双方有了该随机数后就协商生成一个“对话密钥”,通过对称加密技术进行通信。

这样不仅保证了安全性(非对称加密)又不影响通信的效率(非对称加密)。

二.HTTPS

HTTPS是在传输层和应用层中间加入了安全层,从而保证了通信的私密性。



图三 HTTP和HTTPS

三.HTTPS和Android
在访问https://www.baidu.com等使用了安全证书的网站时,客户端代码是可以直接运行的。但是当访问自签名证书的时候客户端就会报如下错误:

javax.net.ssl.SSLHandshakeException:
java.security.cert.CertPathValidatorException:
Trust anchor for certification path not found.


这是因为,该证书不是信任的安全机构颁发,所以不被Android系统所信任。

此时网上会有很多资料说通过覆盖默认的证书验证管理(X509TrustManager)达到正常访问的目的,但是安全隐患会很大。

正常的步骤应该是:

1.生成客户端证书和服务器端证书

   

@echo off
color 0F
rem -------------------------------------------------------------------------
rem 生成https密钥脚本。
rem -------------------------------------------------------------------------

rem 配置项,请修改CN=xxxxxx为对应IP或者域名
set SERVER_DN="CN=10.250.201.243, OU=cn, O=cn, L=cn, ST=cn, C=cn"
set CLIENT_DN="CN=10.250.201.243, OU=cn, O=cn, L=cn, ST=cn, C=cn"
set PASS_SET=password
set FILE_PATH=keyfile

rem 设置当前路径
cd %cd%
echo 当前路径:%cd%

rem 存在文件夹就执行FOUND模块脚本
if not exist "%FILE_PATH%" goto NOT_FOUND
rem 不存在就执行NOT_FOUND模块脚本
goto FOUND

rem 存在文件夹模块脚本.
:FOUND
rd /q/s "%FILE_PATH%"
md "%FILE_PATH%"
cd %FILE_PATH%
goto CREATE

rem 不存在文件夹模块脚本.
:NOT_FOUND
md "%FILE_PATH%"
cd %FILE_PATH%
goto CREATE

rem 生成密钥脚本
:CREATE
echo 开始生成密钥。
echo .
echo ====================================生成服务器端私钥===========================================
keytool -genkey -v -alias jboss -keyalg RSA -keystore jboss.keystore -dname %SERVER_DN% -validity 365000 -storepass %PASS_SET% -keypass %PASS_SET%
echo =====================================生成客户端证书==========================================
keytool -genkey -v -alias client -keyalg RSA -storetype PKCS12 -keystore client.p12 -dname %CLIENT_DN% -validity 365000 -storepass %PASS_SET% -keypass %PASS_SET%
echo =====================================导出客户端公钥==========================================
keytool -export -alias client -keystore client.p12 -storetype PKCS12 -storepass %PASS_SET% -rfc -file %cd%/client.cer
echo =====================================将公钥和私钥合并到jboss.keystore==========================================
echo Y | keytool -import -alias client -v -file client.cer -keystore jboss.keystore -storepass %PASS_SET%
echo ========================================导出服务器端私钥========================================
keytool -export -alias jboss -keystore jboss.keystore -storepass %PASS_SET% -rfc -file server.cer
echo =======================================生成客户端公钥==========================================
echo Y | keytool -import -alias jboss -file server.cer -keystore server_trust.keystore -storepass %PASS_SET% -storetype BKS -providername "BC"
echo ===============================================================================
echo 生成密钥完毕,请把%cd%目录如下文件拷贝文件到服务器jboss下的\server\default\conf路径下。
echo .jboss.keystore
echo .client.cer
echo .client.p12
echo .server.cer
echo .server_trust.keystore
echo ===============================================================================
echo .

pause


生成之前要对环境进行配置:

下载bcprov-jdk15-135.jar(压缩包有对应jdk版本文件中缀就是jdk版本)及sunjce_provider.jar(可能已经存在),放入D:\Java\jdk1.6.0_22\jre\lib\ext下面。同时要修改D:\Java\jdk1.6.0_22\jre\lib\security\java.security文件,

(上面路径对应的是本机的java路径)

找到security.provider.1=sun.security.provider.Sun这行,这里有好几行,在最后一行加上security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider,笔者本来有9号,所以新一行的序号为10。

文件格式介绍:

cer:

在windows下,单独存在的公钥一般是后缀为.cer的文件
keystore:

java用的存储密钥的容器。可以同时容纳n个公钥或私钥,后缀一般是.jks或者.keystore或.truststore等,千奇百怪。不管什么后缀,它就是一个容器,各个公司或机构叫法不同而已。比如把只包含"受信任的公钥"的容器存成.truststore文件等。

证书之间相互转换:

https://www.trustasia.com/tools-cert-converter

2.在客户端代码中加载并设置证书:

/**
* 加载HTTPS证书文件
* @param in  证书文件
*/
public static void loadHttpsKeystore(InputStream in) {
try {
KeyStore trustStore = KeyStore.getInstance("BKS");
trustStore.load(in, "password".toCharArray());//password为证书密码
SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
//严格验证主机名,防止中间人攻击
socketFactory.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
httpClient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", socketFactory, 443));
} catch (Exception e) {
Log.e("Test",e.getMessage(),e);
}
}


3.在服务器端启用HTTPS并设置证书:

以jboss为例,在jboss路径\server\default\deploy\jbossweb-tomcat55.sar\server.xml中拷入(或是更改)如下片段:

<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="${jboss.server.home.dir}/conf/jboss.keystore" keystorePass="password"
keystoreType="jks"


总结:Android中需要使用keystore文件模拟浏览器进行HTTPS通信,使用cer文件和工具可以生成keystore;keystore文件可以设置密码。

自签名的证书不在jdk默认的证书信任列表中,所以需要在代码中导入证书(和在浏览器中导入证书到信任证书机构中原理一样)。

参考资料:
http://blog.jobbole.com/48369/ http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html http://www.oschina.net/translate/android-security-implementation-of-self-signed-ssl
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  https android 加密技术