本文首发于 hzzly的博客面试
原文连接:深究HTTPS算法
前言:尚未用上https的能够看一下我以前写的Nginx下升级https,把你的http升级到https。数组
金九银十或许你也碰到过关于HTTPS的面试问题浏览器
接下来就跟着笔者助你攻破HTTPS。安全
HTTP
:超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协做式和超媒体信息系统的应用层协议。HTTP是万维网的数据通讯的基础。 HTTPS
:超文本传输安全协议(英语:Hypertext Transfer Protocol Secure,缩写:HTTPS,常称为HTTP over TLS,HTTP over SSL或HTTP Secure)是一种经过计算机网络进行安全通讯的传输协议。HTTPS经由HTTP进行通讯,但利用SSL/TLS来加密数据包。HTTPS开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性。bash
从上面概念也能够看出来HTTP是不安全的,且攻击者经过监听和中间人攻击等手段,能够获取网站账户和敏感信息等。HTTPS被设计为可防止前述攻击,并在正确配置时被认为是安全的。服务器
HTTP的URL由"http://"起始且默认使用端口80,而HTTPS的URL由"https://"起始且默认使用端口443。网络
HTTP协议运行在TCP之上,全部传输的内容都是明文,客户端和服务器端都没法验证对方的身份。HTTPS是运行在SSL/TLS之上的HTTP协议,SSL/TLS运行在TCP之上。全部传输的内容都通过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。curl
HTTPS在进行数据传输以前会与服务器和浏览器进行一次握手,在握手时肯定双方的加密密码信息。分布式
具体过程以下:
浏览器将支持的加密信息发送给网站服务器;
服务器会选择出一套加密算法和哈希算法,将验证身份的信息以证书(证书发布CA机构、证书有效期、公钥、证书全部者、签名等)的形式发送给浏览器;
当浏览器收到证书以后首先须要验证证书的合法性,若是证书受到浏览器信任则在浏览器地址栏会有标志显示,不然就会显示不受信的标识。当证书受信以后,浏览器会随机生成一串密码,并使用证书中的公钥加密。以后就是使用约定好的哈希算法握手消息,并生成随机数对消息进行加密,再将生成的信息发送给服务器;
当服务器接收到浏览器发送过来的数据后,会使用服务器自己的私钥将信息解密肯定密码,而后经过密码解密浏览器发送过来的握手信息,并验证哈希是否与浏览器一致。而后服务器会使用密码加密新的握手信息,发送给浏览器;
最后浏览器解密并计算通过哈希算法加密的握手消息,若是与服务发送过来的哈希一致,则此握手过程结束后,服务器与浏览器会使用以前浏览器生成的随机密码和对称加密算法进行加密交换数据。
HTTPS在加密过程当中使用了非对称加密技术和对称加密技术。
采用单钥密码系统的加密方式,同一个密钥能够同时作信息的加密和解密,这种加密的方法称为对称加密。
SSL在通讯过程当中,使用了对称加密算法,也就是说客户端和服务器同时共享一个密钥。
因而,以共享密钥的方式加密,必须将密钥发给对方。这个时候,假如通讯过程被监听,密钥被攻击者获取了,那么这个时候也就失去了加密的意义了。
因而就须要使用两把密钥的非对称加密算法。
与对称加密算法相反,非对称加密算法须要两个密钥来进行加密和解密,这两个密钥是配对的,分别是公开密钥(公钥)和私有密钥(私钥)。
因而如今,假设如今由服务器来生成一对公钥和密钥。
当客户端第一次发请求和服务器协商的时候,服务器就生成了一对公钥和私钥。
紧接着,服务器把公钥发给客户端(明文,不须要作任何加密),客户端接收后,使用服务器发过来的公钥进行数据加密。
再接着,服务器接收到了之后,用配对的私钥进行解密,就获得了客户端发送的数据。
非对称加密算法的特色:算法强度复杂、安全性依赖于算法与密钥可是因为其算法复杂,而使得加解密速度性能上比较差,没有对称加密算法加解密的速度快。
可是咱们还存在一个问题,若是公钥被中间人拿到篡改呢?
这时咱们就须要使用证书保证公钥的正确性
首先,服务器的运营人员向数字证书机构(CA)提出公开密钥的申请。数字证书认证机构在验证申请者的身份以后,会对申请的公开密钥作数字签名,而后分配这个已签名的公开密钥,并将该公开密钥放入公钥证书后绑定在一块儿。
简单点理解就是: CA会向申请者颁发一个证书文件和证书的私钥文件,这个证书文件里面的内容有:签发者、证书用途、服务器申请的时候附带的公钥、服务器的加密算法、使用的HASH算法、证书到期的时间等等,私钥文件就是与证书中公钥对应的私钥。
紧接着,把上面所提到的证书文件里的内容,作一次HASH求值,获得一个HASH值。
再接着,用CA的私钥进行加密,这样就完成了数字签名。而用CA的私钥加密后,就生成了相似人体指纹的签名,任何篡改证书的尝试,都会被数字签名发现。
最后,把数字签名,附在数字证书的末尾,传输回来给服务器。
接下来,服务器会把这份由数字证书认证机构颁发的公钥证书发给客户端。 客户端拿到这个数字证书之后,会去校验证书签名的合法性,先对证书进行SHA256(浏览器的加密算法)获得一个哈希值,而后用证书的公钥对证书的签名进行解密从中取得另外一个哈希值,若是这两个哈希值相等,说明证书没有被篡改过,确实是权威机构颁发。
若是认证经过,就能够取得服务器的公开密钥。
接下来就可使用对称加密算法通讯了。
HTTPS中不只可使用服务器证书,还可使用客户端证书。以客户端证书进行客户端认证,它的做用与服务器证书是相同的。
例如,银行的网上银行就采用了客户端证书(网银盾)。在登陆网银时不只要求用户确认输入ID和密码,还会要求用户的客户端证书(网银盾),以确认用户是否从特定的终端访问网银。
这一步中,客户端经过发送client_hello
报文开始SSL通讯。在请求中,浏览器会带上一些创建链接的必要信息(注意:这一步的信息全都是明文的),包括:
版本
: 客户端支持的最高的 TLS 协议版本。从高到低依次为:TLS v1.2, TLS v1.1, TLS v1.0, SSL v3, SSL v2。其中低于 TLS v1.0 的版本基本再也不使用,由于 SSL v3 和 SSL v2 都存在漏洞,Google 和 Mozilla 已明确禁用 SSL 协议。密码套件
: 按优先级降序排列的、客户端支持的加密套件列表。每一个加密套件会各包含一个认证算法(用于身份验证)、密钥交换算法(用于协商密钥)、对称加密算法(用于消息加密)和信息摘要算法(用于完整性校验)。压缩方法
: 客户端支持的用于压缩消息、下降传输体积的压缩算法列表。随机数
: 一个由客户端生成的随机数,使用 32 位时间戳和一个安全随机数生成器生成的 28 字节随机数组成。这个随机数用于后续Master Key
的生成,并防止重放攻击。会话标识
: 一个变长的会话标志。非 0 值意味着客户端但愿更新当前已存在的链接的参数或者为此链接建立一个新的链接。0 值表示客户端想在新会话上建立一个新链接。扩展字段
: 包含一些其余的相关参数(好比 SNI)。客户端在发出client_hello
消息以后,会等待服务器返回server_hello
消息,包含和 client_hello
相同的参数。通常来讲,参数结构以下:
版本
: 包含客户端支持的最低版本和服务器支持的最高版本。密码套件
: 包含了服务器从客户端发来的密码套件列表中选择出的将要使用的密码套件。压缩方法
: 包含了服务器从客户端发来的压缩方法列表中选择出的将要使用的压缩方法。随机数
: 由服务器生成的不一样于客户端在client_hello
中发来的随机数的另外一个独立的随机数。会话标识
: 若是客户端发送的会话标识不为 0,服务器会使用与客户端发送的一致的会话标识,不然返回的是服务器生成的一个新的会话标识。一般来讲,服务器会在certificate
消息中发送其自身的公开密钥证书供客户端进行验证。
最后,服务器发送server_hello_done
消息,代表服务器的 hello 相关的消息结束。在发送此消息以后,服务器会等待客户端应答,该消息没有参数。
在这一步结束以后代表最初阶段的SSL握手协商部分结束。
客户端在收到服务器发来的server_hello_done
消息以后,会验证服务器提供的证书是否合法,并检查server_hello
的各项参数。若是验证经过,则客户端会向服务器发送一条或多条消息。
而后客户端会发送client_key_exchange
报文消息,报文中包含通讯加密中使用的一种被称为PreMaster Key
的随机密码串,并使用服务器证书中的公钥或者服务器密钥交换消息中的临时 RSA 密钥加密。这个密钥会被用于以后的Master Key
的计算。
通过以上步骤,客户端和服务器已经能够经过获得的消息计算出Master Key
了。从如今开始,客户端和服务器都将开始使用协商好的加密算法、密钥进行通讯,在正式传递消息以前会计算Master Key
和以前握手过程当中收到的全部信息的hash
,并经过协商好的加密算法使用 Master Key
加密,做为change_cipher_spec
消息的内容,接着发送finished
消息。服务器在收到客户端发来的change_cipher_spec
和finished
消息以后,也会计算Master Key
并使用协商好的加密算法和以前握手过程当中收到的全部信息的hash
,发回给客户端用以验证。至此,握手阶段结束,以后就能够交换应用层的内容了。
服务器和客户端的finished
报文交换完毕以后,SSL链接就算创建完成,固然,通讯会受到SSL的保护。今后处开始进行应用层协议的通讯,即发送HTTP请求。
至此,整个过程介绍完毕。
咱们可使用 curl 命令来简略查看创建 HTTPS 时的握手过程,在命令行中执行:curl -v -I -L hzzly.cn
能获得以下的输出:
简单说明一下链接的创建过程:
# 表示创建了和 hzzly.cn 服务器 443 端口的链接。
Connected to hzzly.cn (39.108.182.125) port 443 (#0)
# 客户端发出 client_hello 消息。
TLSv1.2 (OUT), TLS handshake, Client hello (1):
# 服务器发出 server_hello 消息。
TLSv1.2 (IN), TLS handshake, Server hello (2):
# 服务器发出 certificate 消息。
TLSv1.2 (IN), TLS handshake, Certificate (11):
# 服务器发出 server_key_exchange 消息。
TLSv1.2 (IN), TLS handshake, Server key exchange (12):
# 服务器发出 server_done 消息。
TLSv1.2 (IN), TLS handshake, Server finished (14):
# 客户端发出 client_key_exchange 消息。
TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
# 客户端发出加密后的 client_hello 消息。
TLSv1.2 (OUT), TLS change cipher, Client hello (1):
# 客户端发出 hello_done 消息。
TLSv1.2 (OUT), TLS handshake, Finished (20):
# 服务器将加密后的 client_hello 消息发回。
TLSv1.2 (IN), TLS change cipher, Client hello (1):
# 握手结束。
TLSv1.2 (IN), TLS handshake, Finished (20):
# SSL 链接采用 ECDHE-RSA-AES256-GCM-SHA384 密码套件。
# ECDHE 表示密钥交换方法采用椭圆曲线迪菲-赫尔曼交换方法
# RSA 表示密钥交换中使用的签名方式
# AES-256-GCM 表示的是对称加密算法
# SHA-384 表示的是内容完整性校验使用的哈希算法
SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
# 以后的几行包含了证书的内容,包括有效时间、经常使用名、证书签发机构等。
Server certificate:
# Common Name 为 hzzly.cn
subject: CN=hzzly.cn
# 在此时间以前无效
start date: Aug 2 00:00:00 2019 GMT
# 在此时间以后无效
expire date: Aug 1 12:00:00 2020 GMT
# 域名和证书的域名匹配
subjectAltName: host "hzzly.cn" matched certs "hzzly.cn"
# 签发者是 Encryption
issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=Encryption Everywhere DV TLS CA - G1
复制代码