简介
HTTPS
HTTPS(Hypertext Transfer Protocol Secure)是一种网络安全传输协议,是一种用于在不可信网络上进行安全通信的传输协议,HTTPS经由HTTP进行通讯,使用SSL/TLS协议对数据进行加密。主要为解决以下三点问题。
- 通信双方的身份验证
例:登录微信输入用户或与密码,如何确实保证确实是在向微信官方发送信息? - 通信数据的私密性
例:用饭店wifi微信聊天,店内的人可否看到? - 通信数据的完整性
例:吃饭微信支付100,缘何实际扣款666,当时显示消费还是100?
TLS/SSL
SSL安全套接层(Secure Sockets Layer)与TLS传输层安全协议(Transport Layer Security)都是一种用于保障数据安全传输的协议。
SSL由网景公司(Netscape)公司设计,一直发布到SSLv3.0版本,后面其有安全漏洞被许多公司禁用。
TLS由IETF发布,SSL是TLS的前身。
下面是其发布时间表:
TLS/SSL在OSI或TCP/IP模型中的层级
那么TLS/SSL位于OSI或TCP/IP模型中的哪一层呢?以下取自维基百科:
TLS and SSL are defined as ‘operating over some reliable transport layer’, which places them as application layer protocols in the TCP/IP reference model and as presentation layer protocols in the OSI model.
结合下图及上面描述可看出,在OSI模型中TLS/SSL位于表现层,在HTTP(应用层)协议之下。
TLS/SSL工作原理
总体流程如下,用*号标注的是可选流程:
Client Server
ClientHello --------> ServerHello Certificate* ServerKeyExchange* CertificateRequest* <-------- ServerHelloDone Certificate* ClientKeyExchange CertificateVerify* [ChangeCipherSpec] Finished --------> [ChangeCipherSpec] <-------- Finished Application Data <-------> Application Data
Hello Request(可选)
Hello Request是一个用于通知客户端需要重新发起握手的简单通知,客户端可以以
ClientHello相回应,也可以忽略,服务器在任何时间都可以发送此消息。
Client Hello
客户端要建立HTTPS连接时会发送一个ClientHello消息,消息体结构如下:
struct {
ProtocolVersion client_version; //客户端支持的TLS最高版本
Random random; //客户端生成的随机数,用于之后生成会话密钥
SessionID session_id;
CipherSuite cipher_suites<2..2^16-2>; //支持的加密算法,如RSA
CompressionMethod compression_methods<1..2^8-1>; //支持的压缩算法
select (extensions_present) {
case false:
struct {};
case true:
Extension extensions<0..2^16-1>;
};
} ClientHello;
Server Hello
服务器端收到ClientHello消息后,如果有支持的TLS版本和相关算法,会回复客户端一个ServerHello消息,否则会关闭加密通信,所带信息如下:
struct {
ProtocolVersion server_version; //确定使用的SSL/TLS版本
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;
ServerHello消息中确实使用的加密算法(cipher_suite)是从ClientHello消息中 cipher_suites 选择一个出来,如此次微信Web版抓包得到的消息:
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
- ECDHE : 密钥交换算法,用于生成premaster_secret(用于生成会话密钥master secret)
- RSA : 签名算法,用户安全传输premaster_secret
- AES_128 : 连接建立后的数据加密算法
- GCM : 一种对称密钥加密操作的块密码模式
Server Certificate
这条消息将会在服务器发送ServerHello会立即发送给客户端,用于携带服务器证书信息。
struct {
ASN.1Cert certificate_list<0..2^24-1>; //服务器端证书链
}
Server Key Exchange Message(可选)
这条消息是用于会话密钥(premaster secret)生成的,首先这条消息不是必须的,只有在客户端与服务器端双方协商采用的加密算法是DHE_DSS、DHE_RSA、DH_anon
时Server Certificate消息中的服务器证书中的信息不足以生成premaster secret时服务器端才需要发送此消息。
struct {
select (KeyExchangeAlgorithm) {
case dh_anon:
ServerDHParams params;
case dhe_dss:
case dhe_rsa:
ServerDHParams params;
digitally-signed struct {
opaque client_random[32];
opaque server_random[32];
ServerDHParams params;
} signed_params;
case rsa:
case dh_dss:
case dh_rsa:
struct {} ;
/* message is omitted for rsa, dh_dss, and dh_rsa */
/* may be extended, e.g., for ECDH – see [TLSECC] */
};
} ServerKeyExchange;
Certificate Request(请求客户端证书,可选)
如果此次HTTPS连接是双向认证的话,服务器就可以通过此消息请求客户端证书以便进行身份验证。
struct {
ClientCertificateType certificate_types<1..2^8-1>;
SignatureAndHashAlgorithm
supported_signature_algorithms<2^16-1>; //服务器端可处理的签名算法列表
DistinguishedName certificate_authorities<0..2^16-1>;
} CertificateRequest;
微信Web版只需要服务器端认证所以不会发送此消息。
Server Hello Done
此消息由服务器端发送,表示服务器端已经完成了为支持密钥交换(生成premaster key)所做的事情,下面开始等待客户端为密钥交换所要发的消息。
客户端在收到此消息后,要验证服务器端证书是否合法,过期或不合法则浏览器会提示警告。
12306未导入它的证书前就会提示这个。
Client Certificate(客户端证书,可选)
客户端在收到Server Hello Done与Certificate Request后,表示服务器端需要验证客户端证书,这时客户端需要发送此Client Certificate消息给服务器端,即使没有客户端证书也要发个 certificate_list 列表为空的此消息,服务器端未收到或收到此消息后验证客户端证书,验证结果可酌情处理,如关闭加密通信或忽略此错误等。
struct {
ASN.1Cert certificate_list<0..2^24-1>; //客户端证书链
} Certificate;
Client Key Exchange Message
客户端收到Server Hello Done消息后就发送此消息用于将生成的premaster secret(用于生成会话密钥master secret)发送到服务器端。根据所采用的非对称加密的算法不同生成premaster secret的方式有所区别。
- RSA :premaster_secret*是由客户端生成的随机数,用服务器证书中公钥加密后传输,服务器端采用私钥解密。
- Diffie-Hellman: 对于Diffie-Hellman算法而言,双方通过Server Key Exchange Message 与 Client Key Exchange Message 交换两个数即可各自算出相同的加密密钥,用此当premaster_secret。
Client Key Exchange Message 消息结构如下:
struct {
select (KeyExchangeAlgorithm) {
case rsa:
EncryptedPreMasterSecret; //premaster secret
case dhe_dss:
case dhe_rsa:
case dh_dss:
case dh_rsa:
case dh_anon:
ClientDiffieHellmanPublic;
} exchange_keys;
} ClientKeyExchange;
生成会话密钥(master secret)
服务器收到此消息后终于可以生成会话密钥了,我们要解答几个问题:
1.为何要生成master secret?
RSA等非对称加密算法加密大量数据时的性能远小于AES等对称加密算法,所以前面所做的 Key Exchange 操作都是为了生成一个对称加密算法的密钥,以便提高通信性能。
2.master secret的生成方法?
使用前面协商的如SHA_256哈希算法由三个随机数client_random、server_random、premaster_secret生成一个安全随机数,采用三个随机数是为了随机性更强。
3.三个随机数都在不可靠网络上传输,如何保证master secret是保密的?
三个随机数中premaster_secret是保密的,所以master_secret也是保密的。
Certificate Verify(验证客户端证书有效性,可选)
如果是双向认证过程时,客户端会在Client Key Exchange Message之后发送此消息,携带有前面所发消息用客户端证书私钥所做的签名,服务器收到此信息可利用公钥验证,是典型的数字签名验证场景。
struct {
digitally-signed struct {
opaque handshake_messages[handshake_messages_length];
}
} CertificateVerify;
Change Cipher Spec(Client发送密钥改变通知)
客户端生成master secret之后即可发送密钥改变通知通知服务器,以后要使用对称密钥master secret来加密数据了!
Finished(Client握手结束通知)
客户端发送握手结束通知,同时会带上前面所发内容的签名到服务器端,保证前面通信数据的正确性。
Change Cipher Spec(Server发送密钥改变通知)
服务器端收到 Client Key Exchange Message 通知后即可通知客户端已生成master secret,后面的通信数据用此key加密。
Finished(Server握手结束通知)
服务器端发送握手结束通知,同时会带上前面所发内容的签名到客户端,保证前面通信数据的正确性。
核心工作流程
通过上面的分析我们可以得出其解决最开始三个问题的工作方式: 1. 通过签名证书进行通信双方的身份验证。 2. 通过使用非对称加密算法与哈希算法生成的私密会话密钥加密数据来保证数据的私密性。 3. 通过使用私密的会话密钥与哈希算法保证数据不被篡改,因为攻击者无会话密钥,所以无法在修改数据后得到对应的数据检验码。