你们都知道https相比http增长的是安全性。 怎么增长安全性呢? 就是加密和解密步骤。 下面来详细谈谈对https的理解和在Android中的使用.算法
加密方式分两种,对称加密和非对称加密。这两种方式都有本身的优劣势, https中这两种方式都采用了。 咱们约定S是服务端,C是客户端,客户端须要从服务端获取信息;浏览器
这种加密方式比较简单,就是双方都持有密匙。S和C都持有密匙, S经过密匙加密明文传递给C,C获取加密后的信息,用密匙解密信息。优点: 加密速度快, 劣势: 密匙的传递是个问题,容易被截取,密匙一旦被截取后, 就能轻易破解信息。常见的对称加密算法有DES、3DES、TDEA、Blowfish、RC5和IDEA。安全
非对称加密中,S和C端都有本身的公钥和私钥。公钥是公开的,私钥是私有的,私钥须要保密的。 这套公钥和私钥的有个两种加密解密流程:bash
在https中信息传递的密匙的传递是采用非对称加密传递的.
C端须要把信息传递给S端, 须要分几步.服务器
对称加密中,私钥不只须要本身知道也须要解密方知道。 这样私钥就有一个传递的流程, 这个流程就会有很大风险。 而非对称加密只须要本身保密好本身的私钥就行了。 公钥你们都知道,不须要保密,就少了一个私钥传递的过程。 少了很大的风险。网络
HTTPS = HTTP + SSL/TLS协议app
SSL的全称是Secure Sockets Layer,即安全套接层协议,是为网络通讯提供安全及数据完整性的一种安全协议。SSL协议在1994年被Netscape发明,后来各个浏览器均支持SSL,其最新的版本是3.0; TLS的全称是Transport Layer Security,即安全传输层协议,最新版本的TLS创建在SSL 3.0协议规范之上.在理解HTTPS时候,能够把SSL和TLS看作是同一个协议。dom
HTTPS为了兼顾安全与效率,同时使用了对称加密和非对称加密。 数据是被对称加密传输的,对称加密过程须要客户端的一个密钥,为了确保能把该密钥安全传输到服务器端; 采用非对称加密对该密钥进行加密传输,总的来讲,对数据进行对称加密,对称加密所要使用的密钥经过非对称加密传输。ide
一个HTTPS请求实际上包含了两次HTTP传输,能够细分为8步。网站
在https中须要证书,证书的做用是为了防止"中间人攻击"的。 若是有个中间人M拦截客户端请求,而后M向客户端提供本身的公钥,M再向服务端请求公钥,做为"中介者" 这样客户端和服务端都不知道,信息已经被拦截获取了。这时候就须要证实服务端的公钥是正确的.
怎么证实呢? 就须要权威第三方机构来公正了.这个第三方机构就是CA. 也就是说CA是专门对公钥进行认证,进行担保的,也就是专门给公钥作担保的担保公司。 全球知名的CA也就100多个,这些CA都是全球都承认的,好比VeriSign、GlobalSign等,国内知名的CA有WoSign。
不论什么平台,设备的操做系统中都会内置100多个全球公认的CA,说具体点就是设备中存储了这些知名CA的公钥。当客户端接收到服务器的数字证书的时候,会进行以下验证:
通常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格式的CertificateFactory
CertificateFactory 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 != null)
certificate.close();
} catch (IOException e) {
LogUtils.debugInfo("https证书错误1");
}
}
//建立TLS类型的SSLContext对象, that uses our TrustManager
SSLContext sslContext = SSLContext.getInstance("TLS");
//TrustManagerFactory是用于生成TrustManager的,咱们建立一个默认类型的TrustManagerFactory
TrustManagerFactory 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");
}
}
复制代码
须要注意的是,若是自定义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() {
@Override
public void checkClientTrusted(X509Certificate[] chain,
String authType)
throws CertificateException {
}
@Override
public 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();
}
}
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
}
复制代码
本文中分析总结了https的加密流程和在Android中的用法. 但愿对你们有所帮助.