你們都知道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中的用法. 但願對你們有所幫助.