HTTPS 笔记

HTTPS 也可以叫做 HTTP over TLS 或者 HTTP over SSL。

数据在互联网中传输时,中间要经过需要中间节点,而中间节点的安全性并不能被保证,可能会被监听或者修改,而 HTTPS 主要可以防止中间人攻击。

证书

key 文件,私钥

csr(Certificate Signing Request),证书签名请求,这不是证书,可以简单理解成公钥,生成证书时要把这个提交给 CA。

crt (certificate),证书。.crt证书文件,常见于*NIX系统,大多数是 pem 编码。

cer(certificate),也是证书。常见于 Windows 系统,大多数应该是 der 编码。

X.509 是一种证书格式。对X.509证书来说,认证者总是CA或由CA指定的人,一份X.509规定了证书需要包含哪些信息,这些字段包含有关用户及其相应公钥的信息。 X.509的证书文件,一般以.crt结尾,根据该文件的内容编码格式,分为 pem 和 der 二种格式,这两种格式可以互相转换。

pem,Privacy Enhanced Mail。以文本格式存储,以-----BEGIN...开头, -----END...结尾,内容使用 BASE64 编码。(Apache*NIX服务器偏向于使用这种编码格式)

der,Distinguished Encoding Rules,以二进制格式存储,不可读。(Java 和 Windows 服务器偏向于使用这种编码格式)

jks(Java Key Storage)这是 Java 的专利。跟 OpenSSL 关系不大,利用 Java 的一个叫keytool的工具,可以生成.jks文件,也可以将.pfx转为jks

自签名证书:

使用 openssl 来进行 SSL 的操作。(当年大名鼎鼎的「心脏出血」漏洞发生的库哈哈) 生成使用 RSA 算法的私钥server.key

openssl genrsa -des3 -out server.key 2048

使用私钥 server.key ,生成证书请求文件server.csr。这里会进入交互模式,需要填一堆信息,比如组织地址名称邮箱,注意Common Name填域名。

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

使用私钥 server.key,生成X.509 格式证书ca.crt作为 CA 证书

openssl req -new -x509 -days 3650 -key server.key -out ca.crt

用CA的证书ca.crt给自己的证书请求文件server.csr签名和加密。生成自签名证书 server.crt

openssl x509 -req -days 3650 -in server.csr \
  -CA ca.crt  \
  -CAkey server.key \
  -CAcreateserial -out server.crt

获取一个正常证书:

  1. 自己生成一对私钥和证书签名请求文件.csr
  2. .csr文件上传到 CA 认证机构,填写信息。之后 CA 认证机构使用开发者指定的哈希算法,对证书部分内容进行签名(网站域名,网站公钥,此证书哈希算法,比如 MD5 或者 SHA256),然后使用 CA 机构自己的私钥对证书进行加密(有时候把这个签名和加密的过程说成「签名」)。
  3. CA 机构把「签名」过的证书,再发送给申请者手中(一般就是通过邮件)。
  4. 拿到这个 CA 机构「签名」过的证书,就可以正常部署在自己 web 服务器上使用了。

客户端的验证服务端证书的方法:

客户端收到的网站证书主要内容包括:网站域名,网站公钥,此证书哈希算法,比如 MD5 或者 SHA256。这些内容是使用指定的哈希算法签名,然后再经过了 CA 使用自己的私钥使用比如 RSA 算法加密过的。

客户端得到服务器发来的加密证书后,使用各家 CA 储存在客户端本地的公钥对 证书 进行解密,得到这个网站证书的哈希签名。

证书里有一个签名和加密算法字段,比如 sha256RSA 表示,CA机构是使用 SHA256 对证书进行签名,然后使用CA机构的私钥,通过 RSA 算法对签名进行加密的。

使用证书指定的签名算法对证书内容签名,也得到一个签名。

对比两个签名是否一致,如果一致则检查通过。

单向验证流程:

  1. ClientHello。协商本次对话使用的各项参数(客户端发送支持的 SSL / TSL 指定版本,加密组件 Cipher Suite 列表,也就是加密算法和密钥长度)。一个随机数radom1 ,稍后用于生成对话密钥session Key
  2. ServerHello。服务端从这些选项中选出本次使用的参数。服务端的证书。另外也发送一个随机数radom2 ,稍后用于生成对话密钥session Key
  3. Certificate。客户端验证服务端出示的证书,或使用其他方式进行身份验证;
  4. ServerKeyExchange。对将用于保护会话的对称主密钥session Key达成一致。验证通过之后,客户端会生成一个随机数 pre-master secret,然后使用证书中的公钥进行加密,然后传递给服务器端,服务端将使用私钥进行解密得到PreMaster secret。此时,服务端根据 radom1、radom2、pre-master secret 通过一定的算法得出 session Key 和MAC 算法秘钥,作为后面交互过程中使用对称秘钥。同时客户端也会使用 radom1、radom2、pre-master secret,和同样的算法生成 session Key 和 MAC 算法的秘钥。

PreMaster secret前两个字节是TLS的版本号,这是一个比较重要的用来核对握手数据的版本号,因为在 Client Hello 阶段,客户端会发送一份加密套件列表和当前支持的SSL/TLS的版本号给服务端,而且是使用明文传送的,如果握手的数据包被破解之后,攻击者很有可能篡改数据包,选择一个安全性较低的加密套件和版本给服务端,从而对数据进行破解。所以,服务端需要对密文中解密出来对的PreMaster版本号跟之前 Client Hello 阶段的版本号进行对比,如果版本号变低,则说明被篡改,则立即停止发送任何消息。

生成 session Key 的过程中会用到PRF(Pseudorandom Function伪随机方法)来生成一个key_block,然后再使用key_block,生成后面使用的秘钥。

进行内容的传输时,客户端先使用 MAC秘钥 对内容进行摘要,然后把摘要放在内容的后面使用 sessionKey 再进行加密。 服务器端收到之后,先使用 client_write_key 进行解密,然后使用 client_write_MAC_key 对数据完整性进行验证。 服务器端发送的数据,客户端会使用 server_write_keyserver_write_MAC_key 进行相同的操作。