HTTPS和Android

一.非对称加密和对称加密

在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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值