HTTP的缺点
- 通信使用明文(不加密),内容可能会被窃听。
- 不验证通信的身份,因此有可能遭遇伪装。
- 无法验证报文的完整性,所以有可能篡改。
未加密的协议都会出现类似的问题。
HTTPS = HTTP + 加密 + 认证 + 完整性保护
HTTPS 是身披 SSL 外壳的 HTTP。HTTPS 并非是应用层的一种新协议,只是 HTTP 通信接口部分用 SSL 和 TLS 协议代替而已。
原本HTTP直接和TCP通信;使用SSL时,先和SSL通信,再由SSL和TCP通信。
SSL是独立于HTTP协议的,应用层的其他协议也可以配合SSL协议实现网络安全。
相互交换密钥的公开密钥加密技术
SSL使用公开密钥加密的加密处理方式。公开密钥加密使用一对非对称的密钥——公钥、私钥。
公钥加密,私钥解密。客户端持有公钥,用私钥对发送的信息加密;服务器持有私钥,用私钥对客户端发送的密文解密。
注意:客户端的私钥是服务器事先传递过去的,即服务器先生成一对公钥私钥,把私钥发送到客户端,客户端才能用私钥进行加密。
在HTTPS中,对称加密与非对称加密混合使用。因为非对称加密适合加密小量数据,一般数据应使用对称加密进行加密解密。所以在HTTPS中,使用非对称加密的是对称密钥,即客户端把对称密钥用私钥加密发送到服务器,后续服务器用对称密钥加密解密一般的消息。
确保服务端公钥安全
因为客户端需要用服务端的公钥进行加密,所以首先要确保客户端能拿到正确的服务端公钥。公钥在下发的时候会被替换劫持,这里通过第三方认证机(CA)构确认公钥的正确性。
认证的方式通过数字签名校验实现,简单来说就是CA私钥加密HASH(通过内容生成),公钥解密得出HASH,比对从收到的内容生成的HASH是否相等。
这个过程如下:
前提准备:
- 客户端提前安装了CA的公钥。
- 服务端获取CA颁发的证书。
- 服务端生成一对公钥、私钥,私钥自己存着,公钥最终要传给客户端。
- 把公钥登记到CA,CA对公钥内容做HASH,对HASH值用CA私钥加密,密文+公钥打包成证书发送给服务器。
校验流程:
- 服务端发送公钥证书给客户端;
- 客户端对证书中的密文用CA的公钥解密得出HASH,对证书中的公钥内做HASH,对比两个HASH值。正确则提取公钥存到客户端。
- 客户端使用服务端的公钥加密与服务器传输,开始加密通信。使用上述的混合加密方式,即非对称加密交换对称加密密钥,然后双方使用对称密钥进行加密通信。
RSA公钥、私钥的作用助记
既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。
数字签名就是使用私钥对数据摘要进行签名,并附带和数据一起发送。可以起到防篡改、防伪装、防否认的作用。
证书则是由CA机构自己的私钥签发的数字签名。解决的签名的权威性问题,奠定了信任链的基础。
HTTPS安全通信过程
服务端已经生成公钥、私钥,并通过CA获得公钥证书。客户端已经事先安装CA公钥。
具体过程:
- 客->服,Handshake: ClientHello
- 客户端通过发送 Client Hello 报文开始 SSL 通信。
- 报文中包含客户端支持的 SSL 的指定版本、加密组件(Clipher Suite)列表(所使用的加密算法及密钥长度等)。
- 服->客,Handshake: ServerHello
- 服务器进行 SSL 通信,以 Server Hello 报文作为应答。
- 和客户端一样,在报文中包含 SSL 版本以及加密组件。
- 服务器的加密组件内容是从接收到的客户端加密组件内筛选出来的。
- 服->客,Handshake: Certificate
- 服务器发送 Certificate 报文。报文中包含公钥证书。
- 服->客,Handshake: ServerHelloDone
- 最后服务器发送 Server Hello Done 报文通知客户端,最初阶段的 SSL 握手协商部分结束。
- 客->服,Handshake: ClientKeyExchange
- 第一次握手结束后,客户端以 Client Key Exchange 报文作为回应。
- 报文中包含通信加密中使用的一种称为 Pre-master secret 的随机密码串,该密码已用步骤 3 的公钥进行加密。
- 客->服,ChangeCipherSpec
- 客户端继续发送 Change Cipher Spec 报文。告诉服务器之后的通信将采用该密码进行加密。
- 客->服,Handshake: Finished
- 客户端发送 Finished 报文。该报文包含链接至今全部报文的整体校验值。
- 这次握手协商成功的标准是服务器能正确解密该报文。
- 服->客,ChangeClipherSpec
- 服->客,Handshake: Finished
- 客->服,Application Data(HTTP)
- 客户端和服务端的 Finished 报文交换完毕后,SSL 连接建立完成。从此开始发送 HTTP 请求。
- 服->客,Application Data(HTTP)
- 应用层协议通信,发送 HTTP 响应。
- 客->服,Alert: warning, close notify
- 由客户端断开连接。
参考:HTTPS加密流程理解 - fengf233 - 博客园
单向认证与双向认证
上述的HTTPS基本流程就是单向认证,即指认证服务端的证书。单向认证中需要额外代码的情况往往是服务器下发的证书是CA颁发的,而是自签的,所以在检验服务端私钥证书时就要自定义的逻辑。
而双向认证,则是在ServerHelloDone前,发送来自客户端的公钥证书,服务端收到后用根证书解密客户端证书,取出客户端私钥。双向认证在确保了服务端的正确性,也确保了客户端的正确性。
两者过程对比:
单向认证:
- 客->服,发起HTTPS连接请求,把SSL协议版本发送给服务端。
- 服->客,发送服务端把本机公钥证书(server.crt)。
- 客,校验公钥证书(server.crt),取出服务端公钥。
- 客->服,并发送用服务端公钥加密的随机生成密钥R。
- 服,用私钥(server.key)解密得出密钥R。
- 服<->客,用密钥R进行加密通信。
双向认证:
- 同上(客->服,发起HTTPS连接请求,把SSL协议版本发送给服务端)。
- 同上(服->客,发送服务端把本机公钥证书(server.crt))。
- 同上(客,校验公钥证书(server.crt),取出服务端公钥)。
- 客->服,把自己的公钥证书(client.crt)发送给服务端。
- 服,用根证书(root.crt)解密客户端公钥证书,拿到客户端公钥。
- 客->服,发送自己支持的加密方案。
- 服->客,根据双端能力,选择双方都能接受的加密方案,使用客户端公钥加密后发送。
- 客->服,使用私钥解密加密方案,生成随机密钥R,使用服务端公钥加密后发送。
- 同上5(服,用私钥(server.key)解密得出密钥R)。
- 同上6(服<->客,用密钥R进行加密通信)。
参考:
SSL和TLS
SSL 先有,TSL 是以 SSL 为原型开发的协议,有时会统一称该协议为 SSL。
不推荐一直使用HTTPS
- 与明文通信相比,加密通信会消耗更多的 CPU 及内存资源。所以敏感信息才使用 HTTPS 加密通信。
- 证书的费用开销。