这张图清楚的描述了客户端和服务器之间发生了什么。只要你理解了这张图,你就理解了HTTPS通讯过程。
这张图包括了TCP握手过程和TLS握手过程,我们这里只看TLS握手过程。HTTPS实际就是HTTP+TLS. TLS的握手过程就是HTTPS的握手过程。
第一步:Client say Hello
客户端率先发给服务器消息:“你好”。意思是,我准备和你通讯。这组“你好”的消息还包括下面这些信息。
- TLS Version. 这是我的TLS版本号
- A list of cipher suite 这些是客户端支持的加密算法
- SessionID 上图里没提。这是上一个连接的SessionID,如果是新建连接,它是空。
- A random number 这是一个随机数,后面要用到。
- A list of compression method 一组压缩方法,这不是重点。(感兴趣可看: https://tools.ietf.org/html/rfc3749#page-4)
这些信息在ClientHello的代码中是像下面这样的。
struct {
ProtocolVersion client_version;
Random random;
SessionID session_id;
CipherSuite cipher_suites<2..2^16-2>;
CompressionMethod compression_methods<1..2^8-1>;
select (extensions_present) {
case false:
struct {};
case true:
Extension extensions<0..2^16-1>;
};
} ClientHello;
第二步. 服务器回复一个ServerHello,其内容如下
struct {
ProtocolVersion server_version;
Random random;
SessionID session_id;
CipherSuite cipher_suite;
CompressionMethod compression_method;
select (extensions_present) {
case false:
struct {};
case true:
Extension extensions<0..2^16-1>;
};
} ServerHello;
- TLS 版本
- 随机数,后面用
- 加密算法
- SessionID,上一个连接的SessionID。第一次建立连接,它是空
- 压缩方法。
第三步:服务器发送给客户端服务器的证书。
第四步:客户端验证服务器的证书。证书的验证过程:
https://www.weibo.com/ttarticle/p/show?id=2309404446091184570538
然后,客户端生成一个pre-master secret. 接着用服务器证书里的公钥加密这个pre-master secret,发送给服务器。
我不知道怎么样用中文称呼pre-master secret才好,它其实就是一个随机数。
PreMasterSecret的结构如下,它包括2个byte的客户端协议版本号和46个byte的随机数,所以,pre-master secret一共是48个byte.
struct {
ProtocolVersion client_version;
opaque random[46];
} PreMasterSecret;
第五步:服务器用自己的私钥解开pre-master secret, 然后用客户端的随机数、服务器的随机数和pre-master secret这三个参数计算出一个master secret作为对称加密的会话秘钥。
客户端也用这三个参数计算出同样的master secret. 这样,客户端和服务器拥有了一样的会话秘钥。
master_secret的计算函数是下面这样子的。PRF是伪随机函数(pseudo-random function),它接受3个参数,第二个参数是个简单的写死的字符串。
master_secret = PRF(pre_master_secret,
"master secret",
ClientHello.random + ServerHello.random)
接下来,客户端和服务器就会协商出一种加密算法并用这种算法加密消息,后续的应用层面的数据通讯便都用对称加密的方式通讯。
一些问题:
- 网络监听者能破解pre-master secret吗?
不能,因为他没有私钥。所以,他也无法知道对称秘钥。
- 客户端用来加密的公钥可靠吗?
可靠。因为证书是经过客户端验证的,验证成功则表明证书合法,证书合法则公钥可靠。
- 为什么需要随机数?
是为了防止重放攻击。网络攻击者虽然不能破解数据包,但他可以重新发送数据包,以达到欺骗系统的目的。使用随机数可以防止这种情况发生,如果网络攻击者重发握手数据包,则服务器会生成新的随机数,服务器端的master_secret会不一样。被中间人重发的应用层面的数据包服务器就不会认得,连接中断。
- 如果浏览器被控制和破解了,pre-master secret是不是泄露了?
应该是的。但这种破解已经不是“中间人攻击”范畴了。现在的机制,是为了防止中间人攻击。
参考:https://tools.ietf.org/html/rfc2246#page-11