https://xz.aliyun.com/t/1039html
握手消息 | 动做描述 | 消息内容 |
---|---|---|
1. Client —> ClientHello —> Server | 客户端(浏览器)发送一个hello消息给服务端,发起创建SSL会话的请求。并告诉服务端,本身支持哪些加密算法(Cipher Suite List)。除此以外,还须要产生一个随机数(第一个随机数,用于之后生成对称密钥),发送给服务端。 | 1)支持的协议版本,如TLS 1.0版<br/>2)由客户端生成的随机数,用于生成后面的“对称密钥”<br/>3)支持的加密方法,好比RSA公钥加密<br/>4)支持的压缩方法<br/>5)请求的域名<br/> |
2. Server —> ServerHello —> Client | 服务端的首次响应,会肯定加密协议版本,以及加密的算法,也会生成一个随机数(第二个随机数)给客户端。 | 1)协议的版本<br/>2)加密的算法<br/>3)服务端生成的随机数<br/> |
3. Server —> Certificate —> Client | 还会把本身的证书发送给客户端,让客户端进行校验。服务端证书中的公钥也可被用于加密后面握手过程当中生成的对称密钥。 | 1)服务端证书<br/>证书颁发机构的名称<br/>证书自己的数字签名<br/>证书持有者公钥<br/>证书签名用到的Hash算法<br/> |
4. Server --> ServerKeyExchange —> Client | 指定使用哪一种密钥协商协议。服务端能够在ServerKeyExchange以后当即发送CertificateRequest消息,要求校验客户端的证书。 | 1)使用哪一种密钥协商方式<br/>2)密钥协商时客户端须要的信息 |
5. Server —> ServerHelloDone —> Client | 服务器发送ServerHelloDone消息,告知客户端服务器这边握手相关的消息发送完毕。 | |
6. Client —> ClientKeyExchange —> Server | 消息中包含客户端这边的EC Diffie-Hellman算法相关参数,而后服务器和客户端均可根据接收到的对方参数和自身参数运算出对称密钥。 | 1)密钥协商时服务端须要的信息 |
7. Client —> ChangeCipherSpec —> Server | ChangeCipherSpec消息,通知服务器此消息之后客户端会以加密方式发送数据。 | 准备好了作加密传输的通知 |
8. Client —> Finished —> Server | 客户端计算生成对称密钥,而后使用该对称密钥加密以前全部收发握手消息的Hash值,发送给服务器,服务器将相同的会话密钥(使用相同方法生成)解密此消息,校验其中的Hash值。 | |
9. Server —> ChangeCipherSpec —> Client | ChangeCipherSpec消息,通知客户端此消息之后服务器会以加密方式发送数据。 | 准备好了作加密传输的通知 |
10. Server — > Finished —> Client | 服务器使用对称密钥加密(生成方式与客户端相同)以前所发送的全部握手消息的hash值,发送给客户端去校验。 | |
11. Application Data | 真正的数据传输(使用对称加密) |
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;
RSA
AEAD_AES_128_GCM
SHA256
ECDHE
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;
公钥
和私钥
,公钥会作到证书里面,私钥则会给到网站方。网站方的信息
和网站方的公钥
、签名算法
等信息(就是Wireshark Packet 20中的数据,除了“签名值”),计算一个hash值(图中hash算法是SHA256),而后CA再用本身私钥作加密(图中公开密钥算法是RSA),最后的这个密文就是“数字签名”(也就是咱们在图中看到“encrypted”签名值)。* 浏览器一般也会内置大多数主流权威CA的根证书。 * 若是查找不到对应的可信CA,则判断这个证书是伪造的,不可信的。(浏览器则会提醒该证书不是可信任机构颁发的,并询问是否要继续访问)
CA机构证书
里面的公钥
信息,将网站方证书
中的签名值
(也就是数字签名)作解密,获得网站证书
信息的hash摘要A。网站证书
中的信息,作hash获得摘要B,比对摘要A和摘要B是否一致。若是不一致,说明网站证书
中的信息被修改了。(浏览器则会提醒该证书不是可信任机构颁发的,并询问是否要继续访问)公钥
,用于后面的握手签名。证书
公钥对签名值解密,得到摘要A。并将此次数据明文作SHA512的hash,得到摘要B,作比对。(这里对协商算法作签名校验,目的多是防止中间人对协商算法方式作篡改,虽然DH算法不担忧公钥在不安全的网络中传输,可是其余算法可能须要考虑被篡改的状况。因此猜想服务端密钥协商时作签名是这个目的,由于服务端这时已经肯定是DH算法了,因此客户端协商时就不须要作签名了,DH算法不须要考虑这个安全问题)服务端密钥协商的公钥以及本身的公钥
EC Diffie-Hellman
密钥协商协议为例,来看看客户端、服务端是怎么协商出相同的密钥的(这里协商出来的是PreMasterSecret,不是最终的对称加密用到的密钥)。struct { opaque verify_data[verify_data_length]; } Finished; verify_data PRF(master_secret, finished_label,Hash(handshake_messages)) [0..verify_data_length-1];
struct { HandshakeType msg_type; /* handshake type */ uint24 length; /* bytes in message */ select (HandshakeType) { case hello_request: HelloRequest; //HelloRequest是服务端在任什么时候候均可以发出的,告诉客户端须要从新进行握手协议,客户端随即发送新的ClientHello case client_hello: ClientHello; case server_hello: ServerHello; case certificate: Certificate;//服务端或客户端发送本身证书给客户端。 case server_key_exchange: ServerKeyExchange; case certificate_request: CertificateRequest;//服务端请求,客户端发送本身的客户端证书,给服务端作校验。这个步骤在博文中没有提到,看之后有须要再了解。 case server_hello_done: ServerHelloDone; case certificate_verify: CertificateVerify;//客户端发出,从client hello开始,一直到CertificateVerify以前的全部消息的hash加上客户端证书对应私钥的加密结果。 case client_key_exchange: ClientKeyExchange; case finished: Finished; } body; } Handshake;
struct { ProtocolVersion protocol_version; //协议版本 CipherSuite cipher_suite; //加密套件类型 CompressionMethod compression_method; //压缩方法 opaque master_secret[48]; //对称密钥 ClientIdentity client_identity; //客户端ID uint32 timestamp;//ticket有效期 } StatePlaintext;