HTTPS 笔记

作者: 英勇青铜5 | 来源:发表于2018-11-07 19:30 被阅读15次

    主要记录学习工作流程的笔记

    资料

    可以按照先后顺序看下


    1. 握手前须知

    HTTP + 加密 + 认证 + 完整性保护 = HTTPS

    HTTPS = HTTP + TLS/SSLTLSSSL的后继版本,现在一般都用TLS

    SSL是一个二进制协议,通过443端口进行流量传输

    为了安全传输需要对传输内容进行加密,为了解决各种鸡生蛋蛋生鸡的问题,HTTPS中使用对称加密对传输内容进行加密,使用非对称加密来对对称加密的密钥加密

    为了防止非对称加密技术的公钥被掉包替换,需要数字证书来保证公钥的安全性,但由于一个机构要颁发很多证书,为了防止证书被篡改,使用数字签名技术来验证数字证书

    可以看看https原理通俗了解


    数字证书 CA

    1. 证明公开密钥本身就是货真价实的公开密钥。
    2. 证明目标网站是经过 CA 验证的可信任网站

    主要包含:

    • 对象名称,人、服务器、组织等
    • 过期时间
    • 证书发布者,由谁为证书担保
    • 来自证书发布者的数字签名
    数字证书

    图来自 《HTTP 权威指南》

    注意:证书自身也有公钥,服务器也有公钥,证书的公钥为了数字签名,服务器的公钥为了交换对称算法密钥


    数字签名

    验证报文未被伪造或篡改

    使用加密系统对报文进行签名,可以说明报文的来源,同时又可以验证报文的完整性

    数字签名通常是使用非对称加密技术产生。由于私钥只有所有者知道,可以将私钥作为指纹使用

    通过数字签名验证证书

    通过数字签名验证证书

    图来自 SSL/TLS协议详解,共有4篇

    验证数字证书,解决同一机构颁发的不同证书被篡改问题。类比毕业证的编号

    在服务端,根据一个Hash算法计算一个证书Hash值,使用证书的私钥进行加密,也就是签名。客户端拿到证书后,先使用证书公钥对签名进行解密得到一个Hash_1,然后再次使用证书公钥根据指定的算法对证书进行计算,得到Hash_2,比较两个Hash值,相同则认证通过认为证书有效


    通过数字签名验证报文完整性

    验证报文
    1. 节点A提取变长报文为定长摘要
    2. 节点A以用户私钥为参数使用一个签名函数对摘要进行计算。计算出签名后,节点A附加在报文末端,之后将报文和签名发给B
    3. 节点B接收到使用私钥加密后的签名,使用公钥的反函数,得到摘要信息,之后比较摘要版本信息

    RSA的加密系统中,解码函数D已包含私钥,可以作用签名函数使用

    若摘要版本信息不匹配,说明报文被篡改或者发送报文的一端就不是真实的节点A


    2. 握手流程

    在整个Handshake过程中,需要完成:

    1. 交换协议版本号
    2. 选择一个两端都能使用的密码
    3. 对两端身份进行验证
    4. 生成临时会话密钥,以便加密通道

    在最终生成的会话密钥是临时生成的,这样也保证了前向安全

    • 单向认证握手流程
    SSL_Handshak

    图来自 SSL Handshake and HTTPS Bindings on IIS

    会话发起时,先进行TCP的3次握手,成功建立连接后,进行TLS的握手

    可以通过WireshakeGitHub进行抓包,帮助理解学习

    GitHub.com 使用 Wireshake 抓包

    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通过ChromeGithub进行抓包,过滤捕获

    GitHub, Client Helllo

    TLS版本是1.2

    Random就代表着客户端生成的cRandrodm_1数据

    第一次进行TLS握手,Session ID为空

    支持的加密套件列表中有19

    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

    表示:

    使用ECDHE算法交换密钥,RSA进行签名或者公钥验证身份,AES_128_GCM加密传输数据,SHA256来验证数据完整性


    ECDHEECDH的继生版本,支持前向安全性,也就是生成的是临时的密钥。ECDH是基于椭圆曲线的加密算法

    ECDHDH算法的目的都是用于交换密钥而不是加解密,但ECDHDH破解难度更大

    关于密钥交换,可以看看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支持的密码套件有关

    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 SecretcRandrom_3,但服务器端此时还不知道cRandrom_3

    为了让服务器端也知道Pre-Master Secret,需要先进行密钥交换

    看下GitHub.com握手情况

    GitHub.com,第4步

    2.4.1 密钥交换

    客户端进行密钥交换时,根据约定RSADH类算法分两种情况

    RSA是直接加密 Pre-Master Sercet 后发送到服务端,DH类是需要以 Pre-Master Sercet 为参数进行计算,传递的是客户端生成 Pre-Master Sercet 的共享公钥

    若两端问候(Hello)阶段约定好的是用RSA进行交换密钥,服务器端已有对应的私钥,客服端在接到证书后,随机生成48字节的Pre-Master Sercet,之后使用服务器端的公钥对Pre-Master Sercet加密,发送到服务端

    若约定好的是DH类算法,像DHE,ECDHERSA不同,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 KeySessionKey 是一组随机数


    ECDHE算法流程文字描述如下:

    1. 客户端随机生成随机值Ra,计算Pa(x, y) = Ra * Q(x, y),Q(x, y)为全世界公认的某个椭圆曲线算法的基点。将Pa(x, y)发送至服务器
    2. 服务器随机生成随机值Rb,计算Pb(x,y) - Rb * Q(x, y)。将Pb(x, y)发送至客户端
    3. 客户端计算Sa(x, y) = Ra * Pb(x, y);服务器计算Sb(x, y) = Rb *Pa(x, y)
    4. 算法保证了Sa = Sb = S,提取其中的S的x向量作为密钥(预主密钥)

    摘自TLS/SSL 协议详解 (30)


    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的同学,指出来

    相关文章

      网友评论

        本文标题:HTTPS 笔记

        本文链接:https://www.haomeiwen.com/subject/mlkuxqtx.html