HTTPS 协议详解

https

简介

HTTPS (全称:Hypertext Transfer Protocol Secure ),是以安全为目标的 HTTP 通道,在HTTP的基础上通过传输加密和身份认证保证了传输过程的安全性 。HTTPS 在HTTP 的基础下加入SSL,HTTPS 的安全基础是 SSL,因此加密的详细内容就需要 SSL。 HTTPS 存在不同于 HTTP 的默认端口及一个加密/身份验证层(在 HTTP与 TCP 之间)。这个系统提供了身份验证与加密通讯方法。它被广泛用于万维网上安全敏感的通讯,例如交易支付等方面。
HTTPS不是协议,而是通过SSL/TLS协议提供的安全连接进行的HTTP通信。最初,它被用于安全很重要的通信,例如在互联网上传输个人信息和电子支付。 随后,由于公共无线局域网的普及、PRISM的大规模窃听以及中间人攻击的风险增加, 用HTTPS取代单纯的HTTP通信越来越多。
与以纯文本形式发送和接收消息的标准 HTTP 不同,HTTPS 使用SSL/TLS等协议对服务器进行身份验证、加密通信内容和检测篡改。 这样可以防止欺骗、中间人攻击和窃听等攻击。 HTTPS 使用 443 作为已知端口号。

HTTPS 主要由两部分组成:HTTP + SSL / TLS,也就是在 HTTP 上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会通过 TLS 进行加密,所以传输的数据都是加密后的数据。

HTTP 原理
① 客户端的浏览器首先要通过网络与服务器建立连接,该连接是通过TCP 来完成的,一般 TCP 连接的端口号是80。 建立连接后,客户机发送一个请求给服务器,请求方式的格式为:统一资源标识符(URL)、协议版本号,后边是 MIME 信息包括请求修饰符、客户机信息和许可内容。
② 服务器接到请求后,给予相应的响应信息,其格式为一个状态行,包括信息的协议版本号、一个成功或错误的代码,后边是 MIME 信息包括服务器信息、实体信息和可能的内容。

HTTPS 原理
① 客户端将它所支持的算法列表和一个用作产生密钥的随机数发送给服务器;
② 服务器从算法列表中选择一种加密算法,并将它和一份包含服务器公用密钥的证书发送给客户端;该证书还包含了用于认证目的的服务器标识,服务器同时还提供了一个用作产生密钥的随机数;
③ 客户端对服务器的证书进行验证(有关验证证书,可以参考数字签名),并抽取服务器的公用密钥;然后,再产生一个称作 pre_master_secret 的随机密码串,并使用服务器的公用密钥对其进行加密(参考非对称加 / 解密),并将加密后的信息发送给服务器;
④ 客户端与服务器端根据 pre_master_secret 以及客户端与服务器的随机数值独立计算出加密和 MAC密钥(参考 DH密钥交换算法);
⑤ 客户端将所有握手消息的 MAC 值发送给服务器;
⑥ 服务器将所有握手消息的 MAC 值发送给客户端。

HTTP的缺点
HTTP虽然使用极为广泛, 但是却存在不小的安全缺陷, 主要是其数据的明文传送和消息完整性检测的缺乏, 而这两点恰好是网络支付, 网络交易等新兴应用中安全方面最需要关注的。
关于 HTTP的明文数据传输, 攻击者最常用的攻击手法就是网络嗅探, 试图从传输过程当中分析出敏感的数据, 例如管理员对 Web 程序后台的登录过程等等, 从而获取网站管理权限, 进而渗透到整个服务器的权限。即使无法获取到后台登录信息, 攻击者也可以从网络中获取普通用户的隐秘信息, 包括手机号码, 身份证号码, 信用卡号等重要资料, 导致严重的安全事故。进行网络嗅探攻击非常简单, 对攻击者的要求很低。使用网络发布的任意一款抓包工具, 一个新手就有可能获取到大型网站的用户信息。
另外,HTTP在传输客户端请求和服务端响应时, 唯一的数据完整性检验就是在报文头部包含了本次传输数据的长度, 而对内容是否被篡改不作确认。 因此攻击者可以轻易的发动中间人攻击, 修改客户端和服务端传输的数据, 甚至在传输数据中插入恶意代码, 导致客户端被引导至恶意网站被植入木马。

改进目标
HTTPS 协议是由 HTTP 加上 TLS/SSL 协议构建的可进行加密传输、身份认证的网络协议,主要通过数字证书、加密算法、非对称密钥等技术完成互联网数据传输加密,实现互联网传输安全保护。设计目标主要有三个。
(1)数据保密性:保证数据内容在传输的过程中不会被第三方查看。就像快递员传递包裹一样,都进行了封装,别人无法获知里面装了什么。
(2)数据完整性:及时发现被第三方篡改的传输内容。就像快递员虽然不知道包裹里装了什么东西,但他有可能中途掉包,数据完整性就是指如果被掉包,我们能轻松发现并拒收。
(3)身份校验安全性:保证数据到达用户期望的目的地。就像我们邮寄包裹时,虽然是一个封装好的未掉包的包裹,但必须确定这个包裹不会送错地方,通过身份校验来确保送对了地方。

HTTPS协议的改进
* 双向的身份认证
客户端和服务端在传输数据之前,会通过基于X.509证书对双方进行身份认证 。具体过程如下:
* 客户端发起 SSL 握手消息给服务端要求连接。
* 服务端将证书发送给客户端。
* 客户端检查服务端证书,确认是否由自己信任的证书签发机构签发。 如果不是,将是否继续通讯的决定权交给用户选择 ( 注意,这里将是一个安全缺陷 )。如果检查无误或者用户选择继续,则客户端认可服务端的身份。
* 服务端要求客户端发送证书,并检查是否通过验证。失败则关闭连接,认证成功则从客户端证书中获得客户端的公钥,一般为1024位或者 2048位。到此,服务器客户端双方的身份认证结束,双方确保身份都是真实可靠的。 * 数据传输的机密性
客户端和服务端在开始传输数据之前,会协商传输过程需要使用的加密算法。 客户端发送协商请求给服务端, 其中包含自己支持的非对称加密的密钥交换算法 ( 一般是RSA), 数据签名摘要算法 ( 一般是SHA或者MD5) , 加密传输数据的对称加密算法 ( 一般是DES),以及加密密钥的长度。 服务端接收到消息之后,选中安全性最高的算法,并将选中的算法发送给客户端,完成协商。客户端生成随机的字符串,通过协商好的非对称加密算法,使用服务端的公钥对该字符串进行加密,发送给服务端。 服务端接收到之后,使用自己的私钥解密得到该字符串。在随后的数据传输当中,使用这个字符串作为密钥进行对称加密。 * 防止重放攻击
SSL使用序列号来保护通讯方免受报文重放攻击。这个序列号被加密后作为数据包的负载。在整个SSL握手中,都有一个唯一的随机数来标记SSL握手。 这样防止了攻击者嗅探整个登录过程,获取到加密的登录数据之后,不对数据进行解密, 而直接重传登录数据包的攻击手法。

可以看到,鉴于电子商务等安全上的需求,HTTPS对比HTTP,在安全方面已经取得了极大的增强。总结来说,HTTPS的改进点在于创造性的使用了非对称加密算法,在不安全的网路上,安全的传输了用来进行对称加密的密钥,综合利用了非对称加密的安全性和对称加密的快速性 。

优缺点
优点
1. 使用 HTTPS 协议可认证用户和服务器,确保数据发送到正确的客户机和服务器 ;
2. HTTPS 协议是由 SSL+HTTP构建的可进行加密传输、身份认证的网络协议,要比 HTTP安全,可防止数据在传输过程中被窃取、改变,确保数据的完整性。
3. HTTPS 是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本。

缺点
1. 相同网络环境下,HTTPS 协议会使页面的加载时间延长近 50%,增加 10%到 20%的耗电。此外,HTTPS 协议还会影响缓存,增加数据开销和功耗。
2. HTTPS 协议的安全是有范围的,在黑客攻击、拒绝服务攻击和服务器劫持等方面几乎起不到什么作用。
3. 最关键的是,SSL 证书的信用链体系并不安全。特别是在某些国家可以控制 CA 根证书的情况下,中间人攻击一样可行。
4. 成本增加。部署 HTTPS 后,因为 HTTPS 协议的工作要增加额外的计算资源消耗,例如 SSL 协议加密算法和 SSL 交互次数将占用一定的计算资源和服务器成本。在大规模用户访问应用的场景下,服务器需要频繁地做加密和解密操作,几乎每一个字节都需要做加解密,这就产生了服务器成本。随着云计算技术的发展,数据中心部署的服务器使用成本在规模增加后逐步下降,相对于用户访问的安全提升,其投入成本已经下降到可接受程度。

https 历史

发展

网景在1994年创建了HTTPS,并应用在网景导航者浏览器中。 最初,HTTPS是与SSL一起使用的;在SSL逐渐演变到TLS时,HTTPS也由在2000年五月公布的RFC 2818正式确定下来。

版本

超文本传输协议已经演化出了很多版本,它们中的大部分都是向下兼容的。在RFC 2145中描述了HTTP版本号的用法。客户端在请求的开始告诉服务器它采用的协议版本号,而后者则在响应中采用相同或者更早的协议版本。

  • HTTP/0.9
    已过时。只接受GET一种请求方法,没有在通讯中指定版本号,且不支持请求头。由于该版本不支持POST方法,因此客户端无法向服务器传递太多信息。
  • HTTP/1.0
    这是第一个在通讯中指定版本号的HTTP协议版本。
  • HTTP/1.1
    默认采用持续连接(Connection: keep-alive),能很好地配合代理服务器工作。还支持以管道方式在同时发送多个请求,以便降低线路负载,提高传输速度。
  • HTTP/1.1相较于HTTP/1.0协议的区别主要体现在:
    缓存处理,带宽优化及网络连接的使用,错误通知的管理,消息在网络中的发送,互联网地址的维护,安全性及完整性。
  • HTTP/2
    当前版本,于2015年5月作为互联网标准正式发布。
  • HTTP/3
    最新版本,于2022年6月6日标准化为RFC9114。会抛弃使用TCP,通过UDP上使用QUIC来承载应用层数据。
版本 产生时间 内容 发展现状
HTTP/0.9 1991年 不涉及数据包传输,规定客户端和服务器之间通信格式,只能GET请求 没有作为正式的标准
HTTP/1.0 1996年 传输内容格式不限制,增加PUT、PATCH、HEAD、 OPTIONS、DELETE命令 正式作为标准
HTTP/1.1 1997年 持久连接(长连接)、节约带宽、HOST域、管道机制、分块传输编码 2015年前使用最广泛
HTTP/2 2015年 多路复用、服务器推送、头信息压缩、二进制协议等 逐渐覆盖市场

局域网建立 https

相关证书

  • .csr(证书请求文件)
    .csr 是证书请求文件(certificate signing request),是由 RFC 2986定义的PKCS10格式,包含部分/全部的请求证书的信息,比如,主题, 机构,国家等,并且包含了请求证书的公玥,这些被CA中心签名后返回一张证书。返回的证书是公钥证书(只包含公玥不含私钥)
  • .pem(容器格式,证书的加密格式)
    .pem 是一种容器格式,可能仅包含公钥证书,也可以包含完整的证书链(包括公玥,私钥,和根证书)。也可能用来编码 CSR文件。
  • .key(私钥文件,私钥的加密格式)
    .key 其实就是一个pem格式只包含私玥的文件,.key 作为文件名只是作为一个明显的别名。

pem和key 这两种格式 分别存储的是证书base64加密和私钥base64加密还有格式分割符,也就是说pem存的是证书,key 存的是私钥

  • .pkcs12 .pfx .p12(公私钥、证书)
    pkcs即 RSA定义的 公玥密码学( Public-Key Cryptography Standards)标准,有多个标准 pkcs12只是其一,是描述个人信息交换语法标准。 有的文件直接使用其作为文件后缀名。这种文件包含公钥和私钥证书对,跟pem文件不同的是,它的内容是完全加密的。 用openssl可以把其转换成包含公玥和私玥的 .pem 文件。命令: openssl pkcs12 -in file-to-convert.p12 -out converted-file.pem -nodes

  • .der(一种编码方案)
    其实der不是一种文件格式。der 是ASN.1 众多编码方案中的一个,使用der编码方案编码的pem文件。der 编码是使用二进制编码,一般pem文件使用的是base64进行编码,所以完全可以把der编码的文件转换成pem文件,命令: openssl x509 -inform der -in to-convert.der -out converted.pem 使用der编码的pem文件,后缀名可以为.der,也可以为以下格式:

  • .cert .cer .crt(证书)
    pem或者der编码格式的证书文件,这些文件后缀名都会被windows 资源管理器认为是证书文件。有趣的是, .pem 反而不会被认为是证书文件。

  • .crl(证书吊销列表)
    certificate revocation list,证书吊销列表

证书的格式可以相互转换,openssl先生成私钥,然后再生成证书签名请求,最后通过私铜和证书签名请求生成公钥。创建证书签名请求(Certificate signing request)和私钥(Primary key):

openssl req -newkey rsa:2048 nodes out test.csr -keyout test.key

创建公约(Public key)

openssl x509 -reg -days 365 in test.csr -signkey test.key -out test.crt

自签证书

openssl

openssl 自签证书

方式1
# 通过openssl生成私钥
openssl genrsa -out server.key 1024

# 使用私钥生成自签名的cert证书文件,以下是通过参数只定证书需要的信息
openssl req -new -x509 -days 3650 -key server.key -out server.crt -subj "/C=CN/ST=mykey/L=mykey/O=mykey/OU=mykey/CN=domain1/CN=domain2/CN=domain3"
# openssl req:这是openssl工具中用于创建和处理证书签名请求(CSR)的命令。
# -new:这个选项告诉openssl创建一个新的CSR。
# -x509:这个选项告诉openssl生成一个自签名的X.509证书,而不是一个CSR。
# -days 3650:这个选项指定了证书的有效期,这里是3650天,大约10年。
# -key server.key:这个选项指定了私钥文件的位置,即之前使用openssl genrsa命令生成的私钥文件。这个私钥将用于签名自签名证书。
# -out server.crt:这个选项指定了输出证书文件的名称,即生成的自签名证书将被保存为server.crt文件。
# -subj:这个选项允许您直接在命令行中指定证书的主题信息,而不是通过交互式提示输入。
# -subj选项后面的字符串是一个以斜杠(/)分隔的字段,包含了证书的主题信息。这些字段包括:
# /C=CN:国家代码,这里指定为中国(CN)。
# /ST=mykey:州或省份名称,这里指定为mykey。
# /L=mykey:城市或地区名称,这里指定为mykey。
# /O=mykey:组织名称,这里指定为mykey。
# /OU=mykey:组织单位名称,这里指定为mykey。
# /CN=domain1:常用名称(Common Name),这里指定为domain1。通常用于指定域名或服务器名称。
# /CN=domain2:这里又指定了另一个常用名称domain2。
# /CN=domain3:这里指定了第三个常用名称domain3。
方式2
# 通过openssl生成私钥
openssl genrsa -out server.key 1024
# openssl:这是命令行工具的名称,用于执行各种加密操作。
# genrsa:这是openssl的一个命令,用于生成RSA私钥。
# -out server.key:这个选项指定了输出文件的名称,即生成的私钥将被保存为server.key。
# 1024:这是指定的密钥长度,单位是位。这里指定的是1024位。
# 1024位的RSA密钥在当前的安全标准下被认为是不够安全的,因为它可以被相对容易地破解。目前推荐的最小密钥长度是2048位,更安全的实践是使用3072位或4096位的密钥长度。如果您是在进行实际的加密操作,建议使用更长的密钥长度。例如,您可以使用以下命令生成一个2048位的私钥

# 根据私钥生成证书申请文件csr
# 用于创建一个证书签名请求(CSR,Certificate Signing Request)
openssl req -new -key server.key -out server.csr
# openssl req:这是openssl工具中用于创建和处理证书签名请求的命令。
# -new:这个选项告诉openssl创建一个新的CSR。
# -key server.key:这个选项指定了私钥文件的位置,即之前使用openssl genrsa命令生成的私钥文件。这个私钥将用于签名CSR。
# -out server.csr:这个选项指定了输出文件的名称,即生成的CSR将被保存为server.csr文件。
# 执行这个命令后,openssl会提示您输入一些信息,包括您的国家、地区、组织名称、常用名称(通常是您的域名或服务器名称)等。这些信息将被包含在CSR中,并且对于证书颁发机构(CA)来说是很重要的,因为它们会用这些信息来验证您的身份并颁发证书。

# 使用私钥对证书申请进行签名从而生成证书
# 命令是用于将证书签名请求(CSR)转换为自签名证书(self-signed certificate)
openssl x509 -req -in server.csr -out server.crt -signkey server.key -days 3650
# openssl x509:这是openssl工具中用于处理X.509证书的命令。
# -req:这个选项指定输入文件是一个证书签名请求(CSR)。
# -in server.csr:这个选项指定了输入CSR文件的名称,即之前创建的server.csr文件。
# -out server.crt:这个选项指定了输出证书文件的名称,即生成的自签名证书将被保存为server.crt文件。
# -signkey server.key:这个选项指定了用于签名证书的私钥文件,即之前生成的server.key文件。
# -days 3650:这个选项指定了证书的有效期,这里是3650天,大约10年。
方式3
# 直接生成证书文件
openssl req -new -x509 -keyout server.key -out server.crt -config openssl.cnf
# openssl req:这是openssl工具中用于创建和处理证书签名请求(CSR)的命令。
# -new:这个选项告诉openssl创建一个新的CSR。
# -x509:这个选项告诉openssl生成一个自签名的X.509证书,而不是一个CSR。
# -keyout server.key:这个选项指定了私钥文件的输出名称,即生成的私钥将被保存为server.key文件。
# -out server.crt:这个选项指定了输出证书文件的名称,即生成的自签名证书将被保存为server.crt文件。
# -config openssl.cnf:这个选项指定了一个配置文件openssl.cnf,该文件包含了证书的详细配置信息,如国家代码、组织名称、扩展等。

生成CA证书

# 用于生成一个2048位的RSA私钥,并使用三重DES(3DES)算法对其进行加密。
openssl genrsa -des3 -out server.key 2048
# openssl genrsa:这是openssl工具中用于生成RSA私钥的命令。
# -des3:这个选项指定使用三重DES算法对生成的私钥进行加密。您将在生成过程中被要求输入一个密码,以保护私钥。
# -out server.key:这个选项指定了输出文件的名称,即生成的私钥将被保存为server.key。
# 2048:这是指定的密钥长度,单位是位。在这里,您选择了2048位的密钥长度,这在当前的安全标准下是推荐的最小长度。

openssl req -new -key server.key -out server.csr

# 创建一个自签名的X.509证书颁发机构(CA)证书。这个命令将生成一个新的CSR(证书签名请求)和一个自签名的X.509证书,并将它们绑定到同一个命令中。
openssl req -new -x509 -key server.key -out ca.crt -days 3650
# openssl req:这是openssl工具中用于创建和处理证书签名请求的命令。
# -new:这个选项告诉openssl创建一个新的CSR。
# -x509:这个选项告诉openssl生成一个自签名的证书,而不是一个CSR。
# -key server.key:这个选项指定了私钥文件的位置,即之前使用openssl genrsa命令生成的私钥文件。这个私钥将用于签名自签名证书。
# -out ca.crt:这个选项指定了输出证书文件的名称,即生成的自签名CA证书将被保存为ca.crt文件。
# -days 3650:这个选项指定了证书的有效期,这里是3650天,大约10年。

# 用于使用自签名CA证书(ca.crt)和私钥(server.key)来签署一个证书签名请求(CSR),并生成一个新的证书(server.crt)
openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey server.key -CAcreateserial -out server.crt
# openssl x509:这是openssl工具中用于处理X.509证书的命令。
# -req:这个选项指定输入文件是一个证书签名请求(CSR)。
# -days 3650:这个选项指定生成的证书的有效期,这里是3650天(约10年)。
# -in server.csr:这个选项指定了输入CSR文件的名称,即之前创建的server.csr文件。
# -CA ca.crt:这个选项指定了用于签署证书的CA证书,即您之前生成的自签名CA证书。
# -CAkey server.key:这个选项指定了CA证书的私钥,用于签署证书。在这个例子中,您使用的是之前生成的server.key文件。
# -CAcreateserial:这个选项告诉openssl创建一个序列号文件(.srl),用于跟踪证书的序列号。如果您没有提供序列号文件,openssl会自动创建一个。
# -out server.crt:这个选项指定了输出证书文件的名称,即生成的证书将被保存为server.crt文件。

验证证书

# pem 文件不需要指定key,因为pem文件是crt文件和key文件二合一
E:\software_tmp\openssl\bin\openssl.exe s_server -cert .\server.crt -key .\server.key -www
Using default temp DH parameters
ACCEPT

使用证书

docker run -itd -v /E/git/test/openssl/nginx/conf:/etc/nginx/conf.d -v /E/git/test/openssl/nginx/cert:/mnt/cert -v /E/git/test/openssl/nginx/html:/usr/share/nginx/html -v /E/git/test/openssl/nginx/log:/var/log/nginx --network=host nginx:latest
server {
    listen 9901;
    listen 9902 ssl;

    ssl_certificate /mnt/cert/server.crt;
    ssl_certificate_key /mnt/cert/server.key;
    ssl_session_cache shared:sslcache:20m;
    ssl_session_timeout 10m;

    root /usr/share/nginx/html;
    index index.html index.htm;
}

参考文献

苏ICP备19018690号-1