前言:还没有用上https的可以看一下我之前写的Nginx下升级https,把你的http升级到https。
HTTP和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开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性。
HTTP和HTTPS的差异
从上面概念也可以看出来HTTP是不安全的,且攻击者通过监听和中间人攻击等手段,可以获取网站帐户和敏感信息等。HTTPS被设计为可防止前述攻击,并在正确配置时被认为是安全的。
HTTP的URL由”http://“起始且默认使用端口80,而HTTPS的URL由”https://“起始且默认使用端口443。
HTTP协议运行在TCP之上,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。HTTPS是运行在SSL/TLS之上的HTTP协议,SSL/TLS运行在TCP之上。所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。
- 1)对称加密:密钥只有一个,加密解密为同一个密码,且加解密速度快,典型的对称加密算法有DES、AES等;
- 2)非对称加密:密钥成对出现(且根据公钥无法推知私钥,根据私钥也无法推知公钥),加密解密使用不同密钥(公钥加密需要私钥解密,私钥加密需要公钥解密),相对对称加密速度较慢,典型的非对称加密算法有RSA、DSA等。
简述HTTPS访问过程
HTTPS在进行数据传输之前会与服务器和浏览器进行一次握手,在握手时确定双方的加密密码信息。
具体过程如下:
浏览器将支持的加密信息发送给网站服务器;
服务器会选择出一套加密算法和哈希算法,将验证身份的信息以证书(证书发布CA机构、证书有效期、公钥、证书所有者、签名等)的形式发送给浏览器;
当浏览器收到证书之后首先需要验证证书的合法性,如果证书受到浏览器信任则在浏览器地址栏会有标志显示,否则就会显示不受信的标识。当证书受信之后,浏览器会随机生成一串密码,并使用证书中的公钥加密。之后就是使用约定好的哈希算法握手消息,并生成随机数对消息进行加密,再将生成的信息发送给服务器;
当服务器接收到浏览器发送过来的数据后,会使用服务器本身的私钥将信息解密确定密码,然后通过密码解密浏览器发送过来的握手信息,并验证哈希是否与浏览器一致。然后服务器会使用密码加密新的握手信息,发送给浏览器;
最后浏览器解密并计算经过哈希算法加密的握手消息,如果与服务发送过来的哈希一致,则此握手过程结束后,服务器与浏览器会使用之前浏览器生成的随机密码和对称加密算法进行加密交换数据。
HTTPS的加密原理
HTTPS在加密过程中使用了非对称加密技术和对称加密技术。
对称加密算法
采用单钥密码系统的加密方式,同一个密钥可以同时做信息的加密和解密,这种加密的方法称为对称加密。
SSL在通信过程中,使用了对称加密算法,也就是说客户端和服务器同时共享一个密钥。
于是,以共享密钥的方式加密,必须将密钥发给对方。这个时候,假如通信过程被监听,密钥被攻击者获取了,那么这个时候也就失去了加密的意义了。
于是就需要使用两把密钥的非对称加密算法。
非对称加密算法
与对称加密算法相反,非对称加密算法需要两个密钥来进行加密和解密,这两个密钥是配对的,分别是公开密钥(公钥)和私有密钥(私钥)。
于是现在,假设现在由服务器来生成一对公钥和密钥。
当客户端第一次发请求和服务器协商的时候,服务器就生成了一对公钥和私钥。
紧接着,服务器把公钥发给客户端(明文,不需要做任何加密),客户端接收后,使用服务器发过来的公钥进行数据加密。
再接着,服务器接收到了以后,用配对的私钥进行解密,就得到了客户端发送的数据。
非对称加密算法的特点:算法强度复杂、安全性依赖于算法与密钥但是由于其算法复杂,而使得加解密速度性能上比较差,没有对称加密算法加解密的速度快。
但是我们还存在一个问题,如果公钥被中间人拿到篡改呢?
这时我们就需要使用证书保证公钥的正确性
公钥证书
首先,服务器的运营人员向数字证书机构(CA)提出公开密钥的申请。数字证书认证机构在验证申请者的身份之后,会对申请的公开密钥做数字签名,然后分配这个已签名的公开密钥,并将该公开密钥放入公钥证书后绑定在一起。
简单点理解就是:
CA会向申请者颁发一个证书文件和证书的私钥文件,这个证书文件里面的内容有:签发者、证书用途、服务器申请的时候附带的公钥、服务器的加密算法、使用的HASH算法、证书到期的时间等等,私钥文件就是与证书中公钥对应的私钥。
紧接着,把上面所提到的证书文件里的内容,做一次HASH求值,得到一个HASH值。
再接着,用CA的私钥进行加密,这样就完成了数字签名。而用CA的私钥加密后,就生成了类似人体指纹的签名,任何篡改证书的尝试,都会被数字签名发现。
最后,把数字签名,附在数字证书的末尾,传输回来给服务器。
接下来,服务器会把这份由数字证书认证机构颁发的公钥证书发给客户端。
客户端拿到这个数字证书以后,会去校验证书签名的合法性,先对证书进行SHA256(浏览器的加密算法)得到一个哈希值,然后用证书的公钥对证书的签名进行解密从中取得另一个哈希值,如果这两个哈希值相等,说明证书没有被篡改过,确实是权威机构颁发。
如果认证通过,就可以取得服务器的公开密钥。
接下来就可以使用对称加密算法通信了。
扩展:客户端证书
HTTPS中不仅可以使用服务器证书,还可以使用客户端证书。以客户端证书进行客户端认证,它的作用与服务器证书是相同的。
例如,银行的网上银行就采用了客户端证书(网银盾)。在登录网银时不仅要求用户确认输入ID和密码,还会要求用户的客户端证书(网银盾),以确认用户是否从特定的终端访问网银。
HTTPS的安全通信机制
client_hello
这一步中,客户端通过发送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)。
server_hello
客户端在发出client_hello
消息之后,会等待服务器返回server_hello
消息,包含和 client_hello
相同的参数。一般来说,参数结构如下:
版本
: 包含客户端支持的最低版本和服务器支持的最高版本。密码套件
: 包含了服务器从客户端发来的密码套件列表中选择出的将要使用的密码套件。压缩方法
: 包含了服务器从客户端发来的压缩方法列表中选择出的将要使用的压缩方法。随机数
: 由服务器生成的不同于客户端在client_hello
中发来的随机数的另一个独立的随机数。会话标识
: 如果客户端发送的会话标识不为 0,服务器会使用与客户端发送的一致的会话标识,否则返回的是服务器生成的一个新的会话标识。
certificate + server_hello _done
通常来说,服务器会在certificate
消息中发送其自身的公开密钥证书供客户端进行验证。
最后,服务器发送server_hello_done
消息,表明服务器的 hello 相关的消息结束。在发送此消息之后,服务器会等待客户端应答,该消息没有参数。
在这一步结束之后表明最初阶段的SSL握手协商部分结束。
client_key_change
客户端在收到服务器发来的server_hello_done
消息之后,会验证服务器提供的证书是否合法,并检查server_hello
的各项参数。如果验证通过,则客户端会向服务器发送一条或多条消息。
然后客户端会发送client_key_exchange
报文消息,报文中包含通信加密中使用的一种被称为PreMaster Key
的随机密码串,并使用服务器证书中的公钥或者服务器密钥交换消息中的临时 RSA 密钥加密。这个密钥会被用于之后的Master Key
的计算。
change_cipher_spec + finished
经过以上步骤,客户端和服务器已经可以通过得到的消息计算出Master Key
了。从现在开始,客户端和服务器都将开始使用协商好的加密算法、密钥进行通信,在正式传递消息之前会计算Master Key
和之前握手过程中收到的所有信息的hash
,并通过协商好的加密算法使用 Master Key
加密,作为change_cipher_spec
消息的内容,接着发送finished
消息。服务器在收到客户端发来的change_cipher_spec
和finished
消息之后,也会计算Master Key
并使用协商好的加密算法和之前握手过程中收到的所有信息的hash
,发回给客户端用以验证。至此,握手阶段结束,之后就可以交换应用层的内容了。
服务器和客户端的finished
报文交换完毕之后,SSL连接就算建立完成,当然,通信会受到SSL的保护。从此处开始进行应用层协议的通信,即发送HTTP请求。
至此,整个过程介绍完毕。
实践HTTPS连接的握手过程
我们可以使用 curl 命令来简略查看建立 HTTPS 时的握手过程,在命令行中执行:curl -v -I -L https://hzzly.cn
能得到如下的输出:
简单说明一下连接的建立过程:
1 | # 表示建立了和 hzzly.cn 服务器 443 端口的连接。 |
参考
- 《图解http》
- 从Chrome源码看HTTPS