最近在搭建Android框架,将网络分了些模块,本身因为使用OkHttp+Retrofit+RxJava的模式,具体实现不讲了,网上有很多文章
HttpManager
|-基础请求
|-日志模块
|-缓存模块
|-安全模块(Https)
总体结构采用了组合大于继承的模式,日志以及缓存模块都是依赖Interceptor完成的,如有遗漏的希望读者指正,本文的重点在于安全模块,本来还有验证不过现在用的少就不加了
Https
关于https网上有恨多文章,对加密接触不多刚开始看不懂私钥,密钥的验证过程,那么首先来讲讲私钥密钥的概念私钥,密钥详细解释
加密:公钥加密,私钥解密
认证:私钥加密,公钥解密
前方高能,粘贴一个场景,便于理解
首先A有自己的公钥和私钥:A_public_key, A_private_key
B也有自己的公钥和私钥: B_public_key, B_private_key
(1)A和B互换公钥
(2)A将文件用hash算法生成摘要,用A_private_key对摘要加密,得到的就叫数字签名
(3)A用B_public_key对文件加密
(4)将加密的文件和数字签名一起发给B
------B收到内容后
(5)用B_private_key解密文件,得到明文
(6)用A_public_key解密数字签名,得到内容摘要
(7)将明文的文件内容用同样hash算法得到摘要,与第六步的摘要对比。相同则证明内容和来源都正确。
然后我们来具体了解https
http相对于https多了一个s这个s就是ssl(Secure Socket Layer),夹在tcp/ip跟http层之间,接下来看看流程

- 浏览器将自己支持的一套加密算法、HASH算法发送给网站。
- 网站从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了网站地址,加密公钥,以及证书的颁发机构等信息。
浏览器获得网站证书之后,开始验证证书的合法性,如果证书信任,则生成一串随机数字作为通讯过程中对称加密的秘钥。然后取出证书中的公钥,将这串数字以及HASH的结果进行加密,然后发给网站。 - 网站接收浏览器发来的数据之后,通过私钥进行解密,然后HASH校验,如果一致,则使用浏览器发来的数字串使加密一段握手消息发给浏览器。
- 浏览器解密,并HASH校验,没有问题,则握手结束。接下来的传输过程将由之前浏览器生成的随机密码并利用对称加密算法进行加密。
做完了文字说明,接下来就是在OkHttp上实现Https了
public static SSLSocketFactory getSSLSocketFactory() {
try {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null);
int index = 0;
InputStream certificate = new ByteArrayInputStream(CER_12306.getBytes());
String certificateAlias = Integer.toString(index++);
keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
if (certificate != null)
certificate.close();
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
sslContext.init
(
null,
trustManagerFactory.getTrustManagers(),
new SecureRandom()
);
return sslContext.getSocketFactory();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
以上的证书我复制出来了字符串CER_12306
大概流程就是先生成证书放入KeyStore,然后用KeyStore去初始化TrustManager,再用TrustManager获得SSLContext
网友评论