SSL/TLS 协议

背景

不使用 SSL/TLS 的 HTTP 通信,就是不加密的通信。所有信息明文传播,带来了三大风险。

  1. 窃听风险(eavesdropping):第三方可以获知通信内容。
  2. 篡改风险(tampering):第三方可以修改通信内容。
  3. 冒充风险(pretending):第三方可以冒充他人身份参与通信。

SSL/TLS 协议是为了解决这三大风险而设计的,希望达到:

  1. 所有信息都是加密传播,第三方无法窃听。
  2. 具有校验机制,一旦被篡改,通信双方会立刻发现。
  3. 配备身份证书,防止身份被冒充。

互联网是开放环境,通信双方都是未知身份,这为协议的设计带来了很大的难度。而且,协议还必须能够经受所有匪夷所思的攻击,这使得 SSL/TLS 协议变得异常复杂。

历史

互联网加密通信协议的历史,几乎与互联网一样长。

1994 年,NetScape 公司设计了 SSL 协议(Secure Sockets Layer)的 1.0 版,但是未发布。

1995 年,NetScape 公司发布 SSL 2.0 版,很快发现有严重漏洞。

1996 年,SSL 3.0 版问世,得到大规模应用。

1999 年,互联网标准化组织 ISOC 接替 NetScape 公司,发布了 SSL 的升级版 TLS 1.0 版。

2006 年和 2008 年,TLS 进行了两次升级,分别为 TLS 1.1 版和 TLS 1.2 版。最新的变动是 2011 年 TLS 1.2 的修订版

目前,应用最广泛的是 TLS 1.0,接下来是 SSL 3.0。但是,主流浏览器都已经实现了 TLS 1.2 的支持。

TLS 1.0 通常被标示为 SSL 3.1,TLS 1.1 为 SSL 3.2,TLS 1.2 为 SSL 3.3。

SSL/TLS 协议加密过程

第一步,爱丽丝给出协议版本号、一个客户端生成的随机数(Client random),以及客户端支持的加密方法。

第二步,鲍勃确认双方使用的加密方法,并给出数字证书、以及一个服务器生成的随机数(Server random)。

第三步,爱丽丝确认数字证书有效,然后生成一个新的随机数(Premaster secret),并使用数字证书中的公钥,加密这个随机数,发给鲍勃。

第四步,鲍勃使用自己的私钥,获取爱丽丝发来的随机数(即 Premaster secret)。

第五步,爱丽丝和鲍勃根据约定的加密方法,使用前面的三个随机数,生成"对话密钥"(session key),用来加密接下来的整个对话过程。

有三点需要注意:

  1. 生成对话密钥一共需要三个随机数。

  2. 握手之后的对话使用"对话密钥"加密(对称加密),服务器的公钥和私钥只用于加密和解密"对话密钥"(非对称加密),无其他作用。

  3. 服务器公钥放在服务器的数字证书之中。

数字证书

关于数字证书可以看 数字签名是什么? - 阮一峰的网络日志

我们可以通过以下命令生产数字证书。其中 pem 是公钥匙,key 是私钥。

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout mykey.key -out mycert.pem

但是自签名的证书无法得到系统的验证,会有风险提示。所以我们需要把自己当成机构,自己给自己颁发证书,同时将自己的根证书加入到系统中

自签发证书

步骤一: 让自己成为 Certificate Authority。在这一步我们会生成两个文件,分别是私钥文件myCA.key以及公钥myCA.pem. 私钥用于签发证书,公钥用于验证证书。

1
2
openssl genrsa -des3 -out myCA.key 2048 # Generate private key
openssl req -x509 -new -nodes -key myCA.key -sha256 -days 825 -out myCA.pem # Generate root certificate

步骤二:生成网页加密用的密钥$NAME.key和证书签发请求$NAME.csr

1
2
3
NAME=coopers.zone # Use your own domain name
openssl genrsa -out $NAME.key 2048 # Generate a private key
openssl req -new -key $NAME.key -out $NAME.csr # Create a certificate-signing request

步骤三:填写证书基本信息$NAME.ext。注意 DNS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Create a config file for the extensions
>$NAME.ext cat <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = $NAME # Be sure to include the domain name here because Common Name is not so commonly honoured by itself
DNS.2 = *.$NAME # Optionally, add additional domains (I've added a subdomain here)
IP.1 = 192.168.0.13 # Optionally, add an IP address (if the connection which you have planned requires it)
EOF

步骤四:用 CA 私钥签发证书$NAME.crt.

1
2
3
4
# Create the signed certificate
openssl x509 -req -in $NAME.csr \
-CA  myCA.pem -CAkey myCA.key -CAcreateserial \
-out $NAME.crt -days 825 -sha256 -extfile $NAME.ext

最终得到如下文件:myCA.pemcoopers.zone.crt分别是 CA 公钥和网页证书;myCA.keycoopers.key分别是CA私钥和网页私钥。

步骤五:将coopers.zone.keycoopers.zone.crt放到服务器中;将myCA.pem添加到系统根证书中。

参考:ssl - Getting Chrome to accept self-signed localhost certificate - Stack Overflow

参考

  1. SSL/TLS 协议运行机制的概述 - 阮一峰的网络日志
  2. 图解 SSL/TLS 协议 - 阮一峰的网络日志

相关阅读

  1. HTTP 协议入门 - 阮一峰的网络日志
updatedupdated2023-06-052023-06-05
Update https-ca.md