对称加密
- 采用单密钥加密,加解密密钥同一份
- 代表算法: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();