TLS协议分析(四)handshake协议概览
转⾃:/n/1268791652843
5. handshake 协议
handshake protocol重要⽽繁琐。
TLS 1.3对握⼿做了⼤修改,下⾯先讲TLS 1.2,讲完再介绍⼀下分析TLS 1.3.
5.1.handshake的总体流程
handshake protocol⽤于产⽣给record protocol使⽤的SecurityParameters。
在handshake中:
客户端和服务器端协商TLS协议版本号和⼀个CipherSuite,
认证对端的⾝份(可选,⼀般如https是客户端认证服务器端的⾝份),
并且使⽤密钥协商算法⽣成共享的master secret。
步骤如下:
交换Hello消息,协商出算法,交换random值,检查session resumption.
交换必要的密码学参数,来允许client和server协商出premaster secret。
交换证书和密码学参数,让client和server做认证,证明⾃⼰的⾝份。
从premaster secret和交换的random值 ,⽣成出master secret。
把SecerityParameters提供被record层。
允许client和server确认对端得出了相同的SecurityParameters,并且握⼿过程的数据没有被攻击者篡改。
Handshake的结果是在双⽅建⽴相同的Session,Session 包含下列字段:
1.  session identifier
session id,⽤来唯⼀标识⼀个session,在session 恢复的时候,也要⽤到
2.  peer certificate
对端的 X509v3 格式证书. 如果不需要认证对端的⾝份,就为空。
3.  compression method
压缩算法,⼀般被禁⽤
4.  cipher spec
CipherSuite,如上⽂介绍,包含: ⽤于⽣成key的pseudorandom function (PRF) , 块加密算法例如AES, MAC算法 (例如 HMAC-SHA256). 还包括⼀个 mac_length字段,在后⽂的we握⼿协议介绍
5.  master secret
48字节的,client和server共享密钥。
6.  is resumable
⼀个标志位,⽤来标识当前session是否能被恢复。
以上字段,随后被⽤于⽣成 record层的SecurityParameters,多个连接可以通过握⼿协议的session恢复功能来复⽤同⼀个session。
握⼿协议使⽤ ⾮对称加密/密钥协商/数字签名  3类算法,
因此要求读者对这3类算法概念清晰,能准确区分。
在此澄清⼀下,:
⾮对称的算法分为3类:
⾮对称加密,有:RSAES-PKCS1-v1_5,RSAES-OAEP ,Rabin-Williams-OAEP, Rabin-Williams-PKCS1-v1_5等
⾮对称密钥协商,有:DH,DHE,ECDH,ECDHE 等
⾮对称数字签名:RSASSA-PKCS1-v1_5,RSASSA-PSS,ECDSA,DSA,ED25519 等
另外,⾮对称加密算法,可以当作密钥协商算法来⽤,所以 RSAES-PKCS1-v1_5,RSAES-OAEP 也可以当作密钥协商算法来⽤。
插播⼀段 RSA:
其中的 RSAES-PKCS1-v1_5 和 RSASSA-PKCS1-v1_5 是使⽤RSA算法的两种不同scheme(体制)。
RSAES表⽰ RSA Encryption schemes,即⾮对称加密,
RSAES有:RSAES-OAEP,RSAES-PKCS1-v1_5两种,其中RSAES-OAEP更新更安全
RSASSA表⽰ Signature schemes with appendix,即appendix模式(appendix和recovery的区别请参看密码学教材)的⾮对称数字签名算法。
RSASSA有: RSASSA-PSS, RSASSA-PKCS1-v1_5 两种, 其中RSASSA-PSS更新更安全
RSA还有⼀个缺陷,就是很容易被时间侧通道攻击,所以现在的RSA实现都要加 blinding ,后⽂有介绍。
可以看到,RSA是⼀种很特殊的算法,既可以当⾮对称加密算法使⽤,⼜可以当⾮对称数字签名使⽤。这⼀点很有迷惑性,其实很多⽤RSA的⼈都分不清⾃⼰⽤的是RSA的哪种模式。
相⽐之下,ECC(椭圆曲线)这⼀块的算法就很清晰,ECDSA只能⽤作数字签名,ECDH只能⽤作密钥交换。
分清楚 RSAES-PKCS1-v1_5 和 RSASSA-PKCS1-v1_5 有什么⽤涅?
PKCS#1规范解释:
A generally good cryptographic practice is to employ a given RSA
key    pair in only one scheme.  This avoids the risk that
vulnerability in    one scheme may compromise the security of the
other, and may be    essential to maintain provable security.
FIPS PUB 186-3  美国标准规定:
An RSA key pair used for digital signatures shall only be used for one
digital signature scheme (e.g., ANS X9.31, RSASSA-PKCS1 v1.5 or
RSASSA-PSS; see Sections 5.4 and 5.5). In addition, an RSA digital
signature key pair shall not be used for other purposes (e.g., key
establishment).
⼀对密钥只做⼀个⽤途,要么⽤作⾮对称加解密,要么⽤作签名验证,别混着⽤!
⼀对密钥只做⼀个⽤途,要么⽤作⾮对称加解密,要么⽤作签名验证,别混着⽤!cipher命令
⼀对密钥只做⼀个⽤途,要么⽤作⾮对称加解密,要么⽤作签名验证,别混着⽤!
这个要求,决定了⼀个协议的 PFS(前向安全性),在斯诺登曝光NSA的“今⽇捕获,明⽇破解”政策后,越发重要。
PFS反映到密钥协商过程中,就是:
不要使⽤RSA做密钥协商,⼀定只⽤RSA做数字签名。
不要把ECDH的公钥固定内置在客户端做密钥协商
后⽂可以看到这⼀原则在 TLS 1.3,  QUIC,Apple的iMessage等协议中⼀再贯彻。
⾮对称RSA/ECC这个话题⽐较⼤了,后⾯有空再写⽂章吧,读者可以先看⼀下参考资料,⾥⾯有清晰的介绍。
插播结束,继续TLS。
由于设计的时候,就要考虑兼容性,⽽且实际历史悠久,所以TLS协议90年代曾经使⽤的⼀些算法,现在已经被破解了,例如有的被发现漏洞(rc4),有的密钥长度过短(例如曾经美帝有出⼝限制,限制RSA 在512⽐特以下,对称加密密钥限制40⽐特以下,后来2005年限制被取消),但是考虑到兼容,现在的TLS实现中,还是包含了这种已经被破解的⽼算法的代码。这样,如果攻击者可以⼲扰握⼿过程,诱使client和server使⽤这种已经被破解的算法,就会威胁TLS协议的安全,这被称为“降级攻击”。
为了在握⼿协议解决降级攻击的问题,TLS协议规定:client发送ClientHello消息,server必须回复ServerHello消息,否则就是fatal error,当成连接失败处理。ClientHello和ServerHello消息⽤于建⽴client和server之间的安全增强能⼒,ClientHello和ServerHello消息建⽴如下属性:
Protocol Version
Session ID
Cipher Suite
Compression Method.
另外,产⽣并交换两个random值 ClientHello.random 和 ServerHello.random
密钥协商使⽤四条: server的Certificate,ServerKeyExchange,client的Certificate,ClientKeyExchange 。TLS规定以后如果要新增密钥协商⽅法,可以订制这4条消息的数据格式,并且指定这4条消息的使⽤⽅法。密钥协商得出的共享密钥必须⾜够长,当前定义的密钥协商算法⽣成的密钥长度必须⼤于46字节。
在hello消息之后,server会把⾃⼰的证书在⼀条Certificate消息⾥⾯发给客户端(如果需要做服务器端认证的话,例如https)。 并且,如果需要的话,server会发送⼀条ServerKeyExchange消息,(例如如果服务器的证书只⽤做签名,不⽤做密钥交换,或者服务器没有证书)。client对server的认证完成后,server可以要求client发送client的证书,如果这是协商出来的CipherSuite允许的。下⼀步,server 会发送ServerHelloDone消息,表⽰握⼿的hello消息部分已经结束。然后server会等待⼀个client的响应。如果server已经发过了CertificateRequest消息,client必须发送Certificate消息。然后发送ClientKeyExchange消息,并且这条消息的内容取决于ClientHello 和ServerHello消息协商的算法。如果client发送了有签名能⼒的证书,就显式发送⼀个经过数字签名的CertificateVerify消息,来证明⾃⼰拥有证书私钥。
然后,client发送⼀个ChangeCipherSpec消息,并且client拷贝待定的Cipher  Spec到当前的Cipher Spec。然后client⽴即⽤新算法+新key+新密钥 发送Finished消息。收到后,server发送⾃⼰的ChangeCipherSpec消息,作为响应,并且拷贝待定的Cipher Spec到当前的Cipher Spec。此时,握
⼿就完成了,client和server可以开始交换应⽤层数据(如下图所⽰)。应⽤层数据不得在握⼿完成前发送。
Client                                              Server
ClientHello                  -------->
ServerHello
Certificate*
ServerKeyExchange*
CertificateRequest*
<--------      ServerHelloDone
Certificate*
ClientKeyExchange
CertificateVerify*
[ChangeCipherSpec]
Finished                    -------->
[ChangeCipherSpec]
<--------            Finished
Application Data            <------->    Application Data
Figure 1.  Message flow for a full handshake
* 表⽰可选的消息,或者根据上下⽂在某些情况下会发送的消息。Indicates optional or situation-dependent messages that are not
always sent.
注:为了帮助解决管道阻塞的问题,ChangeCipherSpec是⼀个独⽴的TLS protocol content type,并不是⼀个握⼿消息。
TLS的完整握⼿过程,要进⾏RSA/ECDH/ECDSA等⾮对称计算,⾮对称计算是很慢的。关于⾮对称
的性能:
例如在2015年的服务器cpu:  Intel(R) Xeon(R) CPU E3-1230 V2 @ 3.30GHz 上,
使⽤如下命令测试:
openssl speed rsa2048
openssl speed ecdsap256
openssl speed ecdhp256
openssl speed aes-128-cbc
openssl speed -evp aes-128-cbc
结果如下表:
算法性能性能
RSA-2048私钥运算 723.7 次/秒公钥运算 23505.8 次/秒
256 bit ecdsa (nistp256)签名  8628.4 次/秒验证  2217.0 次/秒
256 bit ecdh (nistp256)ECDH协商 2807.8 次/秒
aes-128-cbc加密 121531.39 K/秒
aes-128-cbc 使⽤aesni硬件加速加密 683682.13 K/秒
注:⾮对称的单位是 次/秒,这是由于⾮对称⼀般只⽤于处理⼀个block,
对称的单位是 K/秒,因为对称⼀般⽤于处理⼤量数据流,所以单位和流量⼀样。
可以给⾮对称的 次/秒 乘以 block  size ,就可以和对称做⽐较了。例如rsa-2048,723.72048/8/1024=185.2672 K/秒 ,
故  *RSA-2048 私钥运算性能 是aes-128-cbc 的 1.5/1000。是aesni的 2.6/10000。
如上,性能数据惨不忍睹,  简直不能忍
有鉴于此,TLS从设计之初,就采⽤了万能⼿段—加cache,有2种cache⼿段:session id,和session ticket。把握⼿的结果直接cache 起来,绕过握⼿运算。
当client和server决定恢复⼀个之前的session,或复⽤⼀个已有的session时(可以不⽤协商⼀个新的SecurityParameters),消息流程如下:
客户端使⽤要被恢复的session,发送⼀个ClientHello,把Session ID包含在其中。server在⾃⼰的session cache中,查客户端发来的Session ID,如果到,sever把到的session 状态恢复到当前连接,然后发送⼀个ServerHello,在ServerHello中把Session ID带回去。然后,client和server都必须ChangeCipherSpec消息,并紧跟着发送Finished消息。这⼏步完成后,client和server 开始交换应⽤层数据(如下图所⽰)。如果server在session cache中没有到Session ID,那server就⽣成⼀个新的session ID在ServerHello⾥给客户端,并且client和server进⾏完整的握⼿。
流程图如下:
Client                                                Server
ClientHello                  -------->
ServerHello
[ChangeCipherSpec]
<--------            Finished
[ChangeCipherSpec]
Finished                      -------->
Application Data              <------->    Application Data
Figure 2.  Message flow for an abbreviated handshake
5.2. handshake 协议外层结构
从消息格式来看,TLS Handshake Protocol 在 TLS Record Protocol 的上层. 这个协议⽤于协商⼀个session的安全参数。 Handshake 消息(例如ClientHello,ServerHello等) 被包装进 TLSPlaintext结构⾥⾯,传⼊TLS record层,根据当前session 状态做处理,然后传输。
如下:
enum {
hello_request(0), client_hello(1), server_hello(2),
certificate(11), server_key_exchange (12),
certificate_request(13), server_hello_done(14),
certificate_verify(15), client_key_exchange(16),
finished(20), (255)
} HandshakeType;
struct {
HandshakeType msg_type;  /* handshake type */
uint24 length;          /* bytes in message */
select (HandshakeType) {
case hello_request:      HelloRequest;
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;
case client_key_exchange: ClientKeyExchange;
case finished:            Finished;
case session_ticket:      NewSessionTicket; /* NEW */
} body;
} Handshake;
TLS协议规定,handshake 协议的消息必须按照规定的顺序发,收到不按顺序来的消息,当成fatal error处理。也就是说,TLS协议可以当成状态机来建模编码。
下⾯按照消息发送必须遵循的顺序,逐个解释每⼀条握⼿消息。
handshake协议的外层字段,见这个抓包:
5.3. handshake  — ClientHello,Serv erHello,HelloRequest
Hello消息有3个:ClientHello, ServerHello,HellloRequest
逐个说明:
5.3.1 Cli ent Hello
当客户端第⼀次连接到服务器时,第⼀条message必须发送ClientHello。
另外,rfc⾥规定,如果客户端和服务器⽀持重协商,在客户端收到服务器发来的HelloRequest后,也可以回⼀条ClientHello,在⼀条已经建⽴的连接上开始重协商。(重协商是个很少⽤到的特性。)
消息结构:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。