SSL/TLS 加密传输与数字证书

背景

配置elastic系列产品时,卡了2天在了Enterprise Search 企业搜索实践的证书ssl配置,说明对证书还是有不理解。数字证书、HTTPS、SSL/TLS、加密… 无数的词汇在脑海中席卷而来,这都是些啥啊?为了解答这些困惑,今天这篇文章,我将借此带大家走进 SSL/TLS 加密传输与数字证书,希望从此刻开始,令人眼花缭乱的证书格式不会再成为你的困扰。

本篇着重点在于自签证书

证书与加密

对于数字证书的第一印象,通常来自于 HTTPS 协议。大家都知道HTTP 协议是不需要数字证书的。对于HTTPS协议的理解,可以简单粗暴的认为它约等于 HTTP + SSL,所以,从这个协议诞生的那一刻起,加密算法与数字证书就密不可分,因为从本质上来讲,HTTPS协议就是为了解决如何在不安全的网络上、安全地传输数据的问题。事实上,HTTPS 协议的实现,背后依托 SSL/TLS、数字签名、对称/非对称加密等一系列的知识。也许,在读到这篇文章以前,对于 HTTPS 的理解,永远止步于 HTTP + SSL。那么,我希望下面的解释可以帮助到你,通常,HTTPS 认证可以分为 单向认证 和 双向认证 两种,这里我们以为以单向认证为例,来说明数字证书与加密算法两者间的联系:

S3HoH1

  • 如图所示,HTTPS 单向认证流程主要经历了下面 7 个步骤,它们分别是:
  • 客户端发起 HTTPS 请求
  • 服务器返回证书信息,本质上是公钥
  • 客户端/浏览器通过 CA 根证书验证公钥,如果验证失败,将会收到警告信息
  • 客户端随机生成一个对称密钥 Key,并利用公钥对 Key 进行加密
  • 服务器使用私钥解密获得对称密钥 Key
  • 通过对称密钥 Key 对确认报文进行加密
  • 双方开始通信

由此,我们可以看出,整个 HTTPS 单向认证流程,实际上是结合了 对称加密非对称加密 两种加密方式。
其中,
非对称加密主要用于客户端、服务器双方的“试探”环节,即证书验证部分;
对称加密主要用于客户端、服务器双方的“正式会话”阶段,即数据传输部分。
关于 对称加密 和 非对称加密 两者的区别,我们可以从下面的图中找到答案:
yyhKCA

因为客户端持有服务器端返回的公钥,所以,两者可以使用 非对称加密 对随机密钥 Key 进行加/解密。
同理,因为客户/服务器端使用相同的随机密钥,所以,两者可以使用 对称加密 对数据进行加/解密。

我们来看看天猫这个网站,来看看客户端是怎么对服务端的证书进行校验的。

48bvJ1

事实上,浏览器在对服务器端返回的证书进行校验时,主要关心下面这些信息:

  • 判断域名、有效期等信息是否正确:这些信息在证书中是公开的,可以非常容易地获得。
  • 判断证书是否被篡改:需要由 CA 服务器进行校验。
  • 判断证书来源是否合法:每一份签发的证书都可以按照证书链找到对应的根证书,所以,可以通过操作系统中安装的根证书对证书的来源进行验证。
  • 判断证书是否被吊销:需要由 CRL(Certificate Revocation List,即 证书注销列表)和 OCSP(Online Certificate Status Protocol, 即 在线证书状态协议) 来实现。

这里引入了一个新的概念,即 CA(Certification Authority)。那么,什么是 CA 呢? 通俗来讲,CA 就是一个负责签发、认证和管理证书的机构。可能有朋友会想,客户端和服务器端通过非对称加密相互校验证书就好了啊,为什么还需要这样一个第三方的机构呢?事实上,这相当于一种担保/信用体系,因为服务器端的公钥对任何人来说都是可见的,我们来考虑这样一种情形。假设客户端从服务器端获得了某个公钥,并且它认为这个公钥是可信的,此时,有一个不怀好意的中间人截获了这个公钥,它如法炮制伪造了一个相同的公钥并返回,那么,此时客户端会如何看待这个公钥呢?虽然这个中间人不可能伪造出与服务端相同的私钥,可这无疑会让客户端感到困惑,因为它没有办法判断这个证书的真假。

证书创建

目前,全球主流的 CA 机构有Comodo、Symantec、GeoTrust、DigiCert、Thawte、GlobalSign、RapidSSL 等,其中 Symantec、GeoTrust 都是 DigiCert 机构的子公司,占据数字证书体系中的垄断地位.实际操作中,通常有自签名证书和CA证书两种,两者唯一的差别就在于权威性不同.

CA证书

就是前往Comodo、Symantec、GeoTrust、DigiCert、Thawte、GlobalSign、RapidSSL进行签署,像阿里云腾讯云都有提供相关的证书申请。

自签名证书

所谓自签名证书,其实就是自建一个CA,然后利用这个CA对证书进行签名。
openssl

1
2
3
4
5
6
7
8
9
10
11
12
-new    :说明生成证书请求文件
-x509 :说明生成自签名证书
-key :指定已有的秘钥文件生成秘钥请求,只与生成证书请求选项-new配合。
-newkey :-newkey是与-key互斥的,-newkey是指在生成证书请求或者自签名证书的时候自动生成密钥,
然后生成的密钥名称由-keyout参数指定。当指定newkey选项时,后面指定rsa:bits说明产生
rsa密钥,位数由bits指定。 如果没有指定选项-key和-newkey,默认自动生成秘钥。
-out :-out 指定生成的证书请求或者自签名证书名称
-days :证书的有效期限;
-config :默认参数在ubuntu上为 /etc/ssl/openssl.cnf, 可以使用-config指定特殊路径的配置文件
-nodes :如果指定-newkey自动生成秘钥,那么-nodes选项说明生成的秘钥不需要加密,即不需要输入passphase.
-batch :指定非交互模式,直接读取config文件配置参数,或者使用默认参数值

创建根证书

用openssl x509来自签署。自签署时,使用“-req”选项明确表示输入文件为证书请求文件,否则将默认以为是证书文件,再使用“-signkey”提供自签署时使用的私钥。

1
2
3
4
5
6
// 生成私钥(key文件)
openssl genrsa -out ca.key 2048
// 使用私钥ca.key生成签名请求(csr文件) CSR 即证书签名申请(Certificate Signing Request)
openssl req -new -key ca.key -out ca.csr
// 使用签名请求生成根证书(crt文件)
openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt

或openssl req命令生成自签名证书。

1
2
3
4
// 生成私钥ca.key
openssl genrsa -out ca.key 2048
// 使用私钥ca.key请求并生成根证书pem格式
openssl req -x509 -new -nodes -key ca.key -sha256 -days 365 -out ca.pem

在这个过程中,OpenSSL 会要求我们提供下列信息:国家、省份、城市、组织 以及 全域名(FQDN)。在此之前,关于天猫的那个例子,实际上证书上的那些信息就是从这里来的。当我们有了这样一个自建的 CA 以后,我们就可以用这个自建的 CA 去签发证书,这就是自签名 CA 证书,如何生成这个证书呢?

签发证书
使用 CA 根证书签名服务器证书

1
2
3
4
5
6
// 生成私钥
openssl genrsa -out server.key 2048
// 生成证书请求文件
openssl req -new -key server.key -out server.csr
// 使用 CA 的根证书为服务器证书签名
openssl x509 -req -in server.csr -CA ca.pem -CAkey ca.key -CAcreateserial -out server.crt -days 365 -sha256

证书的编码格式

X.509 标准的证书文件具有不同的编码格式,一般包括 PEM 和 DER 两种。

  • PEM: Privacy Enhanced Mail 的缩写,以文本的方式进行存储。它的文件结构以 —–BEGIN XXX—–,并以 —–END XXX—– 结尾,中间 Body 内容为 Base64 编码过的数据。
    例如,以 PEM 格式存储的证书结构大概如下:
1
2
3
4
5
-----BEGIN CERTIFICATE-----

Base64编码过的证书数据

-----END CERTIFICATE-----

一般 Apache 和 Nginx 服务器应用偏向于使用 PEM 这种编码格式。

  • DER: Distinguished Encoding Rules 的缩写,以二进制方式进行存储,文件结构无法直接预览,同样可以通过如下 OpenSSL 命令查看其证书内容:

一般 Java 和 Windows 服务器应用偏向于使用 DER 这种编码格式。

证书的几种文件扩展名

如上所述,对于 X.509 标准的证书两种不同编码格式,一般采用 PEM 编码就以 .pem 作为文件扩展名,若采用 DER 编码,就应以 .der 作为扩展名。但常见的证书扩展名还包括 .crt、.cer、.p12 等,他们采用的编码格式可能不同,内容也有所差别,但大多数都能互相转换,现总结如下:

  • .csr: Certificate Signing Request 的缩写,即证书签名请求,它并不是证书的格式,而是用于向权威证书颁发机构(Certificate Authority, CA)获得签名证书的申请,其核心内容包含一个 RSA 公钥和其他附带信息,在生成这个 .csr 申请的时候,同时也会生成一个配对 RSA 私钥,私钥通常需要严格保存于服务端,不能外泄。

  • .key: 通常用来存放一个 RSA 公钥或者私钥,它并非 X.509 证书格式,编码同样可能是 PEM,也可能是 DER,查看方式如下

  • .pem: 采用 PEM 编码格式的 X.509 证书的文件扩展名;

  • .der: 采用 DER 编码格式的 X.509 证书的文件扩展名;

  • .crt: 即 certificate 的缩写,常见于类 UNIX 系统,有可能是 PEM 编码,也有可能是 DER 编码,但绝大多数情况下此格式证书都是采用 PEM 编码;

  • .cer: 也是 certificate 的缩写,常见于 Windows 系统,同样地,可能是 PEM 编码,也可能是 DER 编码,但绝大多数情况下此格式证书都是采用 DER 编码;

  • .p12: 也写作 .pfx,全称:PKCS #12,是公钥加密标准(Public Key Cryptography Standards,PKCS)系列的一种,它定义了描述个人信息交换语法(Personal Information Exchange Syntax)的标准,可以用来将包含了公钥的 X.509 证书和证书对应的私钥以及其他相关信息打包,进行交换。简单理解:一份 .p12 文件 = X.509 证书+私钥;

1
2
3
4
5
6
7
8
9
10
11
// .pem -> .pfx
openssl pkcs12 -export -in cert.pem -out cert.pfx -inkey key.pem
// .pfx -> .cer
openssl pkcs12 -in server.pfx -out server.cer -nodes
// .cer -> .pem
openssl x509 -inform der -in server.cer -out server.pem
// PEM -> DER
openssl x509 -in server.pem -outform der -out server.der
// DER -> PEM
openssl x509 -in server.der -inform der -outform pem -out server.pem