赞
踩
大家都知道https相比http增加的是安全性。 怎么增加安全性呢? 就是加密和解密步骤。 下面来详细谈谈对https的理解和在Android中的使用.
加密方式分两种,对称加密和非对称加密。这两种方式都有自己的优劣势, https中这两种方式都采用了。 我们约定S是服务端,C是客户端,客户端需要从服务端获取信息;
这种加密方式比较简单,就是双方都持有密匙。S和C都持有密匙, S通过密匙加密明文传递给C,C获取加密后的信息,用密匙解密信息。优势: 加密速度快, 劣势: 密匙的传递是个问题,容易被截取,密匙一旦被截取后, 就能轻易破解信息。常见的对称加密算法有DES、3DES、TDEA、Blowfish、RC5和IDEA。
非对称加密中,S和C端都有自己的公钥和私钥。公钥是公开的,私钥是私有的,私钥需要保密的。 这套公钥和私钥的有个两种加密解密流程:
在https中信息传递的密匙的传递是采用非对称加密传递的.C端需要把信息传递给S端, 需要分几步.
1.C端请求S端,S端把自己的公钥传递给C端。
2.C用S的公钥把信息加密后传递给S. S用自己的私钥解密获取信息。 常用的非对称加密算法有RSA、Elgamal、Rabin、D-H、ECC(椭圆曲线加密算法)等。
对称加密中,私钥不仅需要自己知道也需要解密方知道。 这样私钥就有一个传递的流程, 这个流程就会有很大风险。 而非对称加密只需要自己保密好自己的私钥就好了。 公钥大家都知道,不需要保密,就少了一个私钥传递的过程。 少了很大的风险。
HTTPS = HTTP + SSL/TLS协议
SSL的全称是Secure Sockets Layer,即安全套接层协议,是为网络通信提供安全及数据完整性的一种安全协议。SSL协议在1994年被Netscape发明,后来各个浏览器均支持SSL,其最新的版本是3.0; TLS的全称是Transport Layer Security,即安全传输层协议,最新版本的TLS建立在SSL 3.0协议规范之上.在理解HTTPS时候,可以把SSL和TLS看做是同一个协议。
HTTPS为了兼顾安全与效率,同时使用了对称加密和非对称加密。 数据是被对称加密传输的,对称加密过程需要客户端的一个密钥,为了确保能把该密钥安全传输到服务器端; 采用非对称加密对该密钥进行加密传输,总的来说,对数据进行对称加密,对称加密所要使用的密钥通过非对称加密传输。
一个HTTPS请求实际上包含了两次HTTP传输,可以细分为8步。
1.客户端向服务器发起HTTPS请求,连接到服务器的443端口。
2.服务器端有一个密钥对,即公钥和私钥,是用来进行非对称加密使用的,服务器端保存着私钥,不能将其泄露,公钥可以发送给任何人。
3.服务器将自己的公钥发送给客户端。
4.客户端收到服务器端的公钥之后,会对公钥进行检查,验证其合法性,如果公钥合格,那么客户端会生成一个随机值,这个随机值就是用于进行对称加密的密钥,我们将该密钥称之为client key,即客户端密钥,这样在概念上和服务器端的密钥容易进行区分。然后用服务器的公钥对客户端密钥进行非对称加密,这样客户端密钥就变成密文了,至此,HTTPS中的第一次HTTP请求结束。
1.客户端会发起HTTPS中的第二个HTTP请求,将加密之后的客户端密钥发送给服务器。
2.服务器接收到客户端发来的密文之后,会用自己的私钥对其进行非对称解密,解密之后的明文就是客户端密钥,然后用客户端密钥对数据进行对称加密,这样数据就变成了密文。
3.然后服务器将加密后的密文发送给客户端。
4.客户端收到服务器发送来的密文,用客户端密钥对其进行对称解密,得到服务器发送的数据。这样HTTPS中的第二个HTTP请求结束,整个HTTPS传输完成。
在https中需要证书,证书的作用是为了防止"中间人攻击"的。 如果有个中间人M拦截客户端请求,然后M向客户端提供自己的公钥,M再向服务端请求公钥,作为"中介者" 这样客户端和服务端都不知道,信息已经被拦截获取了。这时候就需要证明服务端的公钥是正确的.怎么证明呢? 就需要权威第三方机构来公正了.这个第三方机构就是CA. 也就是说CA是专门对公钥进行认证,进行担保的,也就是专门给公钥做担保的担保公司。 全球知名的CA也就100多个,这些CA都是全球都认可的,比如VeriSign、GlobalSign等,国内知名的CA有WoSign。
不论什么平台,设备的操作系统中都会内置100多个全球公认的CA,说具体点就是设备中存储了这些知名CA的公钥。当客户端接收到服务器的数字证书的时候,会进行如下验证:
1.首先客户端会用设备中内置的CA的公钥尝试解密数字证书,如果所有内置的CA的公钥都无法解密该数字证书,说明该数字证书不是由一个全球知名的CA签发的,这样客户端就无法信任该服务器的数字证书。
2.如果有一个CA的公钥能够成功解密该数字证书,说明该数字证书就是由该CA的私钥签发的,因为被私钥加密的密文只能被与其成对的公钥解密。
3.除此之外,还需要检查客户端当前访问的服务器的域名是与数字证书中提供的“颁发给”这一项吻合,还要检查数字证书是否过期等。
一般CA不会直接去使用自己的私钥去签名某网站的证书, 一般CA会签发一个子证书, 然后用这子证书去签网站的证书. 有可能有多个子证书. 如果父证书是可以被信任的,那么这个子证书就是可以被信任的.
在代码中配置https的证书的代码如下:
//配置:
setCertificates(builder, application.getAssets().open("xxxx.cer"));/** * 设置签名证书 * * @param builder * @param certificates */public void setCertificates(OkHttpClient.Builder builder, InputStream... certificates) {try {//创建X.509格式的CertificateFactoryCertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");// 创建一个默认类型的KeyStore,存储我们信任的证书KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());keyStore.load(null);//从asserts中获取证书的流int index = 0;for (InputStream certificate : certificates) {String certificateAlias = Integer.toString(index++);//将证书ca作为信任的证书放入到keyStore中keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));try {if (certificate <img src="https证书错误1");}}//创建TLS类型的SSLContext对象, that uses our TrustManagerSSLContext sslContext = SSLContext.getInstance("TLS");//TrustManagerFactory是用于生成TrustManager的,我们创建一个默认类型的TrustManagerFactoryTrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());trustManagerFactory.init(keyStore);sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());//配置到OkHttpClient 或者builder.sslSocketFactory(sslContext.getSocketFactory());} catch (Exception e) {e.printStackTrace();LogUtils.debugInfo("https证书错误2");}}" style="margin: auto" />
需要注意的是,如果自定义X509TrustManager的时候一定要复写其中三个重要的方法, 如下错误的代码:
TrustManager tm = new X509TrustManager() {public void checkClientTrusted(X509Certificate[] chain, String authType)throws CertificateException {//do nothing,接受任意客户端证书}public void checkServerTrusted(X509Certificate[] chain, String authType)throws CertificateException {//do nothing,接受任意服务端证书}public X509Certificate[] getAcceptedIssuers() {return null;}
};
sslContext.init(null, new TrustManager[] { tm }, null);
正确的做法:
new X509TrustManager() {@Overridepublic void checkClientTrusted(X509Certificate[] chain,String authType)throws CertificateException {}@Overridepublic void checkServerTrusted(X509Certificate[] chain,String authType)throws CertificateException {for (X509Certificate cert : chain) {// Make sure that it hasn't expired.cert.checkValidity();// Verify the certificate's public key chain.// ca是通过证书流获取的证书try {cert.verify(((X509Certificate) ca).getPublicKey());} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (NoSuchProviderException e) {e.printStackTrace();} catch (SignatureException e) {e.printStackTrace();}}}@Overridepublic X509Certificate[] getAcceptedIssuers() {return new X509Certificate[0];}}}
本文中分析总结了https的加密流程和在Android中的用法. 希望对大家有所帮助.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。