主要记录学习工作流程的笔记
资料
- Http基础知识学习(四),了解HTTPS
- 通俗理解数字签名,数字证书和https
- https原理通俗了解
- SSL Handshake and HTTPS Bindings on IIS
- SSL/TLS协议详解,共有4篇
- 说人话的 HTTPS 协议简述——揭秘 Handshake 过程
可以按照先后顺序看下
1. 握手前须知
HTTP + 加密 + 认证 + 完整性保护 = HTTPS
HTTPS = HTTP + TLS/SSL
,TLS
是SSL
的后继版本,现在一般都用TLS
SSL
是一个二进制协议,通过443端口
进行流量传输
为了安全传输需要对传输内容进行加密,为了解决各种鸡生蛋蛋生鸡
的问题,HTTPS
中使用对称加密对传输内容进行加密,使用非对称加密来对对称加密的密钥加密
为了防止非对称加密技术的公钥被掉包替换,需要数字证书
来保证公钥的安全性,但由于一个机构要颁发很多证书,为了防止证书被篡改,使用数字签名
技术来验证数字证书
可以看看https原理通俗了解
数字证书 CA
- 证明公开密钥本身就是货真价实的公开密钥。
- 证明目标网站是经过 CA 验证的可信任网站
主要包含:
- 对象名称,人、服务器、组织等
- 过期时间
- 证书发布者,由谁为证书担保
- 来自证书发布者的数字签名
图来自 《HTTP 权威指南》
注意:证书自身也有公钥,服务器也有公钥,证书的公钥为了数字签名,服务器的公钥为了交换对称算法密钥
数字签名
验证报文未被伪造或篡改
使用加密系统对报文进行签名,可以说明报文的来源,同时又可以验证报文的完整性
数字签名通常是使用非对称加密技术产生。由于私钥只有所有者知道,可以将私钥作为指纹
使用
通过数字签名验证证书
通过数字签名验证证书图来自 SSL/TLS协议详解,共有4篇
验证数字证书,解决同一机构颁发的不同证书被篡改问题。类比毕业证的编号
在服务端,根据一个Hash
算法计算一个证书Hash
值,使用证书的私钥进行加密,也就是签名。客户端拿到证书后,先使用证书公钥对签名进行解密得到一个Hash_1
,然后再次使用证书公钥根据指定的算法对证书进行计算,得到Hash_2
,比较两个Hash
值,相同则认证通过认为证书有效
通过数字签名验证报文完整性
验证报文- 节点
A
提取变长报文为定长摘要 - 节点
A
以用户私钥为参数使用一个签名函数对摘要进行计算。计算出签名后,节点A
附加在报文末端,之后将报文和签名发给B
- 节点
B
接收到使用私钥加密后的签名,使用公钥的反函数,得到摘要信息,之后比较摘要版本信息
在RSA
的加密系统中,解码函数D
已包含私钥,可以作用签名函数使用
若摘要版本信息不匹配,说明报文被篡改或者发送报文的一端就不是真实的节点A
2. 握手流程
在整个Handshake
过程中,需要完成:
- 交换协议版本号
- 选择一个两端都能使用的密码
- 对两端身份进行验证
- 生成临时会话密钥,以便加密通道
在最终生成的会话密钥
是临时生成的,这样也保证了前向安全
- 单向认证握手流程
会话发起时,先进行TCP
的3次握手,成功建立连接后,进行TLS
的握手
可以通过Wireshake
对GitHub
进行抓包,帮助理解学习
2.1 第一步,Client Hello
第1步,Client Hello图来自 ,Van Bruce大佬的小专栏 说人话的 HTTPS 协议简述——揭秘 Handshake 过程
握手第一步,客户端发送Hello报文
Client
生成一个cRandrom_1
,客户端将cRandrom_1
以及TLS
版本,自己支持的加密套件列表,会话 id
等信息发送给服务端
cRandrom_1 在生成最终的临时会话密钥时会用到
随机数是一个32
字节的数据。前4
个字节表示epoch
格式的日期,纪元时间是自1970年1月1日
以来的秒数,后28
个字节就是由加密强随机数生成器生成的随机数
数据是明文发送
使用Wireshark
通过Chrome
对Github
进行抓包,过滤捕获
TLS
版本是1.2
Random
就代表着客户端生成的cRandrodm_1
数据
第一次进行TLS
握手,Session ID
为空
支持的加密套件列表中有19
个
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
表示:
使用ECDHE
算法交换密钥,RSA
进行签名或者公钥验证身份,AES_128_GCM
加密传输数据,SHA256
来验证数据完整性
ECDHE
是ECDH
的继生版本,支持前向安全性
,也就是生成的是临时的密钥。ECDH
是基于椭圆曲线的加密算法
ECDH
和DH
算法的目的都是用于交换密钥而不是加解密,但ECDH
比DH
破解难度更大
关于密钥交换,可以看看SSL/TLS协议详解(上):密码套件,哈希,加密,密钥交换算法了解下
AES_128_GCM
称为批量加密算法,这里表示AES
是一个常用的对称加密算法,密钥长度为128
,采用GCM
模式
AES
是 块密码,也就是对输入的纯文本用固定长度的块来进行加密,加密后的每个块按再顺序发送,最后按类似的方式来进行解密
关于这些加密算法,目前只求个面熟,了解下目的
2.2 第二步,Server Hello
第2步,Server Hello当服务端收到Client Hello
后,必须要发送Server Hello
信息
服务器先进行检查TLS
版本,以及客户端算法的条件
如果服务器能接受并支持所有条件,将会发送证书及其他信息;否则,服务器会发送握手失败信息
过程中,服务端会生成 第二个随机数sRandrom_2
,并确认出具体的加密方法,这些信息在下一步会随证书一起发给客户端
服务器生成的sRandrom_2
也是32
字节,但前4
字节表示服务器的Unix
纪元时间
证书中包含有服务器的公钥
这一步中,数据也是明文的
所有的服务器都不会在这一步发送证书
GitHub , ServerHelllo
服务器响应0x0303
表示服务器同意使用TLS 1.2
服务器端这时已经确定并发送给了客户端具体的加密套件
服务器端会生成Session id
,发送给客户端后,客户端会写入约定的参数到此Session id
,并给定过期时间
再次发起会话时,客户端将在Client Hello
中包含此Session id
若客户端在到期时间之前再次连接到服务器,则服务器可以检查Session id
对应的缓存参数,并重用它们而无需完全握手
Cipher suite
是两端约定好的加密算法
2.3 第三步,服务端发送证书,并进行服务器密钥交换(可选)
服务器密钥交换(Server Key Exchange)是可选的,GitHub.com
中,有这个操作,这和GitHub
支持的密码套件有关
2.3.1 Certificate 证书信息
进行完成第二步,服务器会先进行Certificate
握手,也就是向客户端发送证书
通过抓包,证书消息共3078
字节,这是GitHub.com
所有服务器信息的证书。服务器按信任链的顺序发送完整的证书列表
该链中的第一个是服务器证书,接着是颁发服务器证书的intermediate CA
的证书,然后是下一个intermediate CA
的证书......直到Root CA
的证书。服务器不可以发送Root CA
证书,因为在大多数情况下,浏览器可以从任何intermediate CA
识别Root CA
对于GitHub
来说,使用SHA256
来生成Hash
值,RSA
用于签名
2.3.2 服务器密钥交换 Server Key Exchange
为什么 GitHub 必须要这一步骤?
在第二步,GitHub
选择的Session
的密码套件是TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
客户端和服务器端使用ECDHE(Elliptic Curve Diffie Hellman)
来进行交换密钥,由于在DH(Diffie-Hellman)
中,客户端无法自行计算生成预主密钥(Pre-master secret)
,需要从服务端获取DH
的公钥,服务器便单独在这个握手中发送公钥
服务器密钥交换完成之后,再发送一个Server Helloe Done
消息进行通知,客户端接到后开始准备计算Pre-Master Secret
2.4 第四步,客户端证书验证,密钥交换,向服务器发送测试加密数据
第4步,生成Pre-Master Secret接到服务端证书后,客户端先根据证书携带的信息对证书进行验证,证书验证通过后,客户端再生成第三个随机数cRandrom_3
,这个随机数做为预主密钥(Pre-Master Secret)
到了此时,两端一共产生了3
个随机数,这个时候客户端知道cRandrom_1,sRandRom_2
以及用来做为Pre-Master Secret
的cRandrom_3
,但服务器端此时还不知道cRandrom_3
为了让服务器端也知道Pre-Master Secret
,需要先进行密钥交换
看下GitHub.com
握手情况
2.4.1 密钥交换
客户端进行密钥交换时,根据约定RSA
及DH类
算法分两种情况
RSA是直接加密 Pre-Master Sercet 后发送到服务端,DH类是需要以 Pre-Master Sercet 为参数进行计算,传递的是客户端生成 Pre-Master Sercet 的共享公钥
若两端问候(Hello)
阶段约定好的是用RSA
进行交换密钥,服务器端已有对应的私钥,客服端在接到证书后,随机生成48
字节的Pre-Master Sercet
,之后使用服务器端的公钥对Pre-Master Sercet
加密,发送到服务端
若约定好的是DH类
算法,像DHE,ECDHE
和RSA
不同,DH类
算法并非加解密算法,是密钥协商算法
GitHub.com
使用的是ECDHE
来进行交换密钥,服务端在第3
步的Server Key Exchange
握手前计算生成了服务器端的公-私
密钥对,并把公钥在Server Key Exchange
握手阶段,发送给客户端,通知客户端后面需要进行私钥交换
客户端接收到服务器端的公钥后,使用自身的公-私
钥,以Pre-Master Sercet
为参数进行计算,得到一个共享密钥
,然后在Client Key Exchange
发送给服务端
客户端自身也会通过cRandrom_1 + sRandrom_2 + PreMaster Sercet
计算 Master Sercet
,但 Master Sercet还不是最终用来加密的对称密钥
得到Master Sercet
后,再经过一系列复杂计算后,最终生成用于对称加密的Session Key
,SessionKey 是一组随机数
ECDHE算法流程文字描述如下:
- 客户端随机生成随机值Ra,计算Pa(x, y) = Ra * Q(x, y),Q(x, y)为全世界公认的某个椭圆曲线算法的基点。将Pa(x, y)发送至服务器
- 服务器随机生成随机值Rb,计算Pb(x,y) - Rb * Q(x, y)。将Pb(x, y)发送至客户端
- 客户端计算Sa(x, y) = Ra * Pb(x, y);服务器计算Sb(x, y) = Rb *Pa(x, y)
- 算法保证了Sa = Sb = S,提取其中的S的x向量作为密钥(预主密钥)
2.4.2 Change Cipher Spec,Encrypted_Handshake_Message
当客户端发送了共享密钥后,计算出加密用的对称密钥后,客户端发送Change Cipher Spec
握手消息通知服务器之后的消息都是加密的
接着,客户端便根据之前所有握手消息的信息,计算出一个Hash
值,并使用协商出的加密算法加密,发送给服务端
2.5 第五步,服务器还原 Premaster Secret,并回复加密测试验证消息
第5步,服务器还原 Premaster Sercet服务器根据算法,还原出Premaster Secret
,这时服务器也拥有了cRandrom_1 + sRandrom_2 + PreMaster Sercet
,也可以根据协商,计算出最终的对称加密用Session key
注意:在计算得到 Master Sercet 后,客户端和服务端都会删除各自的私钥
GitHub.com 握手第5步
同客户端一样,完成一系列操作,生成Session key
后,计算出之前所有握手消息的Hash
值,并将客服端发来的加密信息解密出来,进行比对校验,验证密钥和数据的正确性
验证通过后,服务端结合当前所有握手消息的信息计算Hash
值,再使用自己生成的对称密钥加密,发送给客户端
当客户端接收到服务端的Encrypted_Handshake_Message
后,对密钥和数据校验通过时,意味着握手阶段结束,之后便是进行加密通信
大致的握手流程就是这些
3. 补充
本篇中是以GitHub来抓包帮助学习的,是单向认证
证书是静态的,为了保证密钥的随机,加入Pre Master Sercet
做为一种随机因子。然而单单一个Pre Master Sercet
还不足以完全随机
,采用cRandrom_1 + sRandrom_2 + PreMaster Sercet
三个随机数来使密钥更加随机,更难暴力破解
在整个握手过程中,最终加密用到的对称密钥是不会在两端进行传输的。传输的只是3
个随机数,其中前两个随机数是明文传输,而最后一个是加密传输的
在计算出Master Sercet
后,会将两端各自的私钥进行删除
关于会话缓存过程,可以看看HTTPS协议详解(四):TLS/SSL握手过程
再看下,整个握手流程
整个握手流程4. 最后
很多地方还不懂,先把了解的记录下,这次的学习了解收获还是挺多的。Wireshake
这个软件也刚学会一点,以后多用用,能帮助理解
应该会有很多错误的地方,希望比较熟悉HTTPS
的同学,指出来
网友评论