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等使用了安全证书的网站时,客户端代码是可以直接运行的。但是当访问自签名证书的时候客户端就会报如下错误:
这是因为,该证书不是信任的安全机构颁发,所以不被Android系统所信任。
此时网上会有很多资料说通过覆盖默认的证书验证管理(X509TrustManager)达到正常访问的目的,但是安全隐患会很大。
正常的步骤应该是:
1.生成客户端证书和服务器端证书
生成之前要对环境进行配置:
下载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.在客户端代码中加载并设置证书:
3.在服务器端启用HTTPS并设置证书:
以jboss为例,在jboss路径\server\default\deploy\jbossweb-tomcat55.sar\server.xml中拷入(或是更改)如下片段:
总结: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中使用了非对称加密技术和对称加密。非对称加密的好处是私钥和公钥分离,公钥加密,私钥解密,向外只暴露公钥。所以即使得到了公钥也无法解密。缺点是效率低下;
非对称加密(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
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories