HTTPS简介
HTTPS(Hyper Text Transfer Protocol Secure)是在HTTP的基础上结合SSL/TLS协议握手,实现数据安全传输。SSL/TLS是应用层的协议,介于 TCP 和 HTTP 之间的一层安全协议,不影响原有的 TCP 协议和 HTTP 协议,所以使用 HTTPS 基本上不需要对 HTTP 页面进行太多的改造。研究HTTPS协议安全相关的原理,最终就是研究SSL/TLS协议。
SSL/TLS使用了非对称加密(RSA / DSA),但由于非对称加密计算量大,速度慢。所以实际的做法是服务端利用非对称加密生成的公钥生成一个对称加密的秘钥,将其传给客户端后。服务端和客户端都利用该秘钥进行加密解密。
HTTPS握手(RSA)
- RSA流程:
- 假设服务端使用的密码组是TLS_RSA_WITH_AES_128_CBC_SHA。
- 服务端首先查询KeyManager,给客户端返回Certificate/public key。
- 客户端接收Certificate/public key,然后用TrustManager验证Certificate。
- 如果客户端接受该Certificate,则用SecureRandom生成一个随机字节码,并使用Public key对这个随机字节码加密,并作为真正加密用的对称秘钥嵌入Client Key Exchange消息中发送给服务端。
- 服务端利用Private key解密之后,重新获得前一步生成的随机字节码(对称秘钥),然后用改对称秘钥解密数据。
- DSA流程:
- 假设服务端使用的密码组是TLS_DHE_DSS_WITH_AES_128_CBC_SHA。
- 双方都使用KeyPairGenerator生成一个临时的DH 公私密钥对(需要用到KeyFactory和DHPublicKeySpec)。
- 双方都创建一个KeyAgree对象,并用自己的DH私钥初始化。
- 服务端发送ServerKeyExchange消息(附带服务端公钥),客户端发送ClientKeyExchange消息(附带客户端公钥)。两个公钥同时塞入KeyAgreement对象,然后KeyAgreement根据这两个公钥生成一个真正加密使用的Key(对称加密秘钥)。
- 双方使用前一步生成的对称加密秘钥对加密数据相互交互。
-
结论:
DSA比RAS更安全是因为使用了四个秘钥,而且不需要公开的证书,所以使得破解双方数据更难。
中间人劫持(MITM:Man-in-the-middle attack)
对客户端把自己伪装成服务端,对服务端把自己伪装成客户端,从而实现查看传输的全部内容。
- 客户端发送http请求,中间人进行劫持
- 中间人伪装成客户端,向发送http请求
- 服务端传公钥给中间人,中间人自己生成私钥公钥,然后传公钥给客户度
- 客户端生成秘钥(前提中间人公钥通过客户端的验证),利用中间人的公钥加密并把秘钥传给中间人
- 中间人利用自己的私钥解密,并利用服务端的公钥加密传给服务端
- 服务端用自己的私钥解密出客户端的秘钥
- 客户端、中间人、服务端使用相同的秘钥进行传输,中间人可以窜改服务端和客户端的内容。
- charles抓包、mock数据就是典型的中间人劫持
Charles获取Https内容
中间人劫持过程第4中,客户端获取中间人的公钥,只要让客户端通过该公钥的验证,就可以实现https劫持,而要做到通过验证,只需要将三方自己的CA签发的数字证书安装到手机中并且作为受信任证书保存即可。
-
选择SSL Proxying,选择安装证书到移动设置
-
根据提示做(手机连好代理,去网站下载证书进行安装)
3.设置代理,添加需要代理的host
客户端如何验证公钥合法
服务端给客户端实际上是一本证书,这个证书里面包含了
- 公钥
- 各种信息
- 签名
这个签名是服务端用私钥 对 “各种信息” 进行加密生成的,客户端拿到证书里的公钥,对签名进行解密,解密后得到的各种信息和证书里的各种信息进行对比,如果相等则保证了证书是合法的。
但如果中间人使用合法的证书,依然可以进行攻击,如上述的Charles,那么如何预防。
1.内置证书
将真正的证书预先内置在客户端app中,用该证书里的公钥对服务端下发的签名进行解密,解密失败或者和各种信息信息不一致,则断开连接。不过这种方式会有证书过期的问题,一般只有安全性要求非常高的app才会这么做,如一些银行app。
2.通过证书合法性、域名校验等
参考:
HTTPS连接过程以及中间人攻击劫持
HTTPS原理以及Java实现
Android _实现SSL解决不受信任的证书问题