對稱加密
- 採用單密鑰加密,加解密密鑰同一份
- 代表算法:DES、3DES、AES、RC2、RC4
- 優點:加解密效率高,算法簡單,適合加密大量數據。
- 缺點:密鑰維護複雜,泄漏後就沒有安全性可言
非對稱加密
- 非對稱加密公私鑰,一個密鑰用於加密,另外一個解密
- 代表算法:RSA、ECC
- 優點:安全性高,由公鑰無法推導私鑰,適應網絡傳輸場景
- 缺點:加密效率偏低
HTTP/HTTPS
APP網絡應用場景
- 使用http,不做任何加密相當於裸奔,初級工程師都可以輕易窺探你全部的業務數據。
- 使用http,但所有的流量都通過預埋在客戶端的key進行AES加密,流量基本安全,不過一旦客戶端代碼被反編譯竊取key又會會到裸奔狀態
- 使用http,但AES使用的key通過客戶端以GUID的方式臨時生成,爲來保證key能安全送達服務器,勢必要使用服務器的公鑰進行加密,所以要預埋服務器證書,又涉及到證書過期更新機制,而且無法動態協商使用的對稱加密算法,安全性還是又暇疵。
加密傳輸安全建議
- 儘量使用https
- 不要明文傳輸密碼
- 請求帶上數據簽名防篡改
- http請求使用臨時密鑰
- AES使用CBC模式
- post並不比get安全,都要加密和簽名處理
https證書校驗
-
CA(Certificate Authority).CA用自己的私鑰簽發數字證書,數字證書中包含A的公鑰。然後B可以用CA的根證書中的公鑰來解密CA簽發的證書,從而拿到合法的公鑰
-
中間CA:大多數CA不直接簽署服務器證書,而是簽署中間CA,然後用中間CA來簽署服務器證書。這樣根證書可以離線存儲來確保安全,及時中間證書出來問題,可以用根證書重新簽署中間證書。
-
證書校驗:HTTPS握手開始後,服務器會把整個證書鏈發送到客戶端,給客戶端做校驗。校驗的過程是要找到這樣一條證書鏈,鏈中每個相鄰節點,上級的公鑰可以校驗通過下級的證書,鏈的根節點是設備信任的錨點。
https配置
服務端
- 服務端生成公私鑰對
- 給Tomcat服務器配置https
- 導出證書
客戶端
- 將證書集成到APK文件中
- 發送網絡請求,獲取證書,讀取https網站的數據
https API
HttpsURLConnection
URL url = new URL("https://google.com");
HttpsURLConnection urlConnection = url.openConnection();
InputStream in = urlConnection.getInputStream();
SSLSocketFactory
private synchronized SSLSocketFactory getDefaultSSLSocketFactory() {
try {
SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, null, null);
return defaultSslSocketFactory = sslContext.getSocketFactory();
} catch (GeneralSecurityException e) {
throw new AssertionError();
}
}
TrustManager
public interface X509TrustManager extends TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException;
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException;
public X509Certificate[] getAcceptedIssuers();
}
https驗證證書問題
SSLHandshakeException
- 頒發服務器證書的CA未知
- 服務器證書不是CA簽名的,而是自簽名的
- 服務器配置缺少中間CA
自定義信任策略
// 取到證書的輸入流
InputStream stream = getAssets().open(“server.crt");
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); keystore.load(null);
Certificate certificate =
CertificateFactory.getInstance("X.509").generateCertificate(stream);
// 創建Keystore包含我們的證書 keystore.setCertificateEntry(“ca", certificate);
// 創建TrustManager,僅信任keyStore中的證書
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); tmf.init(keyStore);
//用TrustManager初始化一個SSLContext
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
URL url = new URL(path);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(context.getSocketFactory());
指示HttpsUrlConnection信任指定CA
InputStream in = urlConnection.getInputStream();