本网站相关文章:

What is DC?

参考: 数字证书

非对称加密

一个 Public Key, 一个 Private Key, 对于原始内容 origin

  • 使用公钥对信息进行加密public_encrypt_origin = PublicKey(origin), 得到 public_encrypt_origin
  • 使用私钥对信息进行加密private_encrypt_origin = PrivateKey(origin), 得到 private_encrypt_origin

此时接收方可以使用Private Key对加密字符串public_encrypt_origin进行解密, 使用Public Key对加密字符串private_encrypt_origin进行解密.

非对称加密不同于对称加密, 后者仅仅存在一种密钥, 由双方持有, 不能透露给第三方,
非对称加密则可以将公钥透露给用户. 非对称加密在证书流程中主要用于保证数据保密性服务. 常用的非对称加密RSA, DH, 用于数据保密性服务.

对称加密

加密和解密都使用同一个密钥, 这是最为传统的加密算法, 其中密钥的安全限定了该加密算法的使用范围. 常用的对称加密RC2, RC4, IDEA, DES, AES, 用于数据的加解密, 数据的保密性服务.

数字签名

数字签名-signature, 使用非对称加密的公钥或者私钥, 对原始内容进行Hash + Encrypt之后产生的数据, 一般用于确保数据的完整性的, 避免他人恶意篡改, 用于保证数据的完整性抗否认性. 常用的数字签名算法RSA, DSA.

消息摘要

加密过程中不需要密钥, 经过加密之后的数据在相当程度上是无法解密, 相同的数据经过同一个消息摘要算法会得到相同的密文. 因为不存在密钥的管理和分发, 常用于分布式网络中.

常用的消息摘要算法MD5, SHA, 获取不可逆的数据, 用于对数字证书进行摘要, 确保数据的完整性.

数字证书

CA-Certificate Authority, 数字授权中心, 用于发放管理公共合法的证书, 相当于民选政府.
CA 使用自己的 CA-Private-key 对第三方的 Public Key 以及冗余信息进行加密, 生成了数字证书(Digital Certificate).

为何要使用 CA?

设想如下的情况, ClientA 和 ServerB 分别持有公钥 PublicK, 私钥 PrivateK, 在正常逻辑下, ClientA 可以通过公钥对原始信息加密, 在 ClientA 和 ServerB 之间实现安全通信.

asymmetric

但是, 如果此时 ClientA 的网络被劫持, 当访问钓鱼网站或者访问 ServerB 的流量被重定向到 ServerA, 此时 ServerA 极力将自己伪装成一个正义, 公正的 ServerB, 并向 ClientA 发放新的 PublicK, 那么整个流程就会变为这样:

dangerous-asymmetric

为了避免上述情况的发生, 就需要一个代表真正的自由, 平等, 公正, 法治的政府机构来为你确认你当前访问的服务器时合法, 合理, 合规的.

ca

其中为了确保 CA 公钥是正常的(毕竟存在反政府武装), 一般而言, CA 公钥内置在 Browser 中, 在各种信任机制上确保该流程是正常的.

术语

证书标准以及编码格式, 其中 pem 参考: SSL 知识点:

  • X.509: 证书标准, 定义了证书应该包含哪些内容
  • pem: 一种对证书的编码格式, 使用 Base64 编码证书, 应用于 Apache/Nginx
  • der: 一种对证书的编码格式, 使用二进制编码证书, 应用于 Java 环境/Windows 服务器

证书的文件扩展名, 注意, 以 pem/der 编码格式的文件不一定以.pem, .der为文件扩展名, 下面主要介绍几种不同的证书文件扩张名:

  • CRT: 常见于 Unix 系统, 大部分是 pem 编码, 但是也有可能是 der 编码
  • CER: 常见于 Windows 系统, 大部分为 der 编码, 但是也存在 pem 编码
  • KEY: 用于存放 Public key, Private Key, 而并非存放 X.509 证书, 可能为 pem 编码, 有可能是 der 编码
  • CSR: 证书签名请求, 并非证书或者密钥, 而是保存获取签名证书申请的各类信息, 包含一个公钥信息
  • PFX/P12: Windows 的 IIS 则将 CER/KEY 存在一个 PFX 文件中, 如果想从 PFX 中提取信息, 需要提供提取密码

关于上述几个不同扩展名文件的生成, 见 3.3 节的例子说明.

SSL 协议

Introduction

SSL(Secure Sockets Layer)安全套接层, 为网络通信提供安全数据完整性的安全协议.
TLS(Transport Layer Security)传输层安全协议, 保证两个应用程序之间的保密性数据完整性的协议.

关于 SSL 和 TLS, 这里主要讲解两者的历史来理解两者的关系:

  • 1994 年,NetScape 公司设计了 SSL 的 1.0 版
  • 1995 年, NetScape 发布 SSL 2.0
  • 1996 年, NetScape 发布 SSL 3.0, SSL 开始大规模的使用
  • 1999 年, ISOC 接替 NetScape, 发布了 SSL 的升级版 TLS 1.0
  • 2006 年, TLS 1.1
  • 2008 年, TLS 1.2
  • 2011 年, TLS 1.2 修订版

SSL 协议族中有 4 大协议, 分别为:

  • SSL Record Protocol: 建立在 TCP/IP 之上, 为其他三个高层协议提供数据的压缩, 封装, 加密等支持
  • SSL Handshake Protocol: 建立在 SSL 记录协议之上, 用于协商, 身份认证, 密钥交换等
  • SSL Change Cipher Spec Protocol: 每隔一段时间, C/S 之间利用该协议改变加密规范, 在握手协议中被使用
  • SSL Alert Protocol: 为通信实体的对方发送告警信息(Fatal 错误, Warning 消息), 例如返回非法信息

SSL 协议族和 TCP/IP 协议族的关系:

1
2
3
4
5
6
7
握手协议  |  修改密文协议  |  报警协议
--------------------------------------
记录协议
--------------------------------------
TCP协议
--------------------------------------
IP协议

记录协议

将 SSL 消息拆分成一条条记录, 一个 record 包含记录头, 记录数据, 类似 TCP/IP 协议.

握手协议

握手协议在两个应用实体进行数据传输之前进行证书认证, 算法协商, 密钥交换等,
整个握手协议流程如下:
握手协议

在握手协议中, C/S 都是通过请求第三方证书认证机构来验证证书是否有效, 最终通过三个随机数据以及
主密钥来构建会话密钥, 一旦会话密钥构建完毕, 表示整个握手过程结束, 进行正式信息交互
阶段.

证书

使用场景

设想如下的情况, ClientA 和 ServerB 分别持有公钥 PublicK, 私钥 PrivateK, 在正常逻辑下, ClientA 可以通过公钥
对原始信息加密, 并对原始信息进行数字签名, 在 ClientA 和 ServerB 之间实现安全通信/完整通信.

asymmetric

但是, 如果此时 ClientA 的网络被劫持, 当访问钓鱼网站或者访问 ServerB 的流量被重定向到 ServerA, 此时 ServerA 极力
将自己伪装成一个正义, 公正的 ServerB, 并向 ClientA 发放新的 PublicK, 那么整个流程就会变为这样:

dangerous-asymmetric

这种情况在普通用户进行上网的时候是非常普遍的, 例如流量被中间人代理, 并向普通用户传送一个假的公钥, 注意普通用户
不持有私钥, 私钥一般为服务提供方持有. 为了避免上述情况的发生, 就需要一个代表真正的自由, 平等, 公正, 法治
政府机构来为你确认你当前访问的服务器时合法, 合理, 合规的.

ca

其中为了确保 CA 公钥是正常的(毕竟存在反政府武装), 一般而言, CA 公钥内置在 Browser 中, 在各种信任机制上确保
该流程是正常的, 普通用户在每次访问https://www.unusebamboo.com会自动验证本地的公钥是否是对的, 如果确认正确,
才开始进行正常的通信, 此时就算流量被中间人代理, 代理也无法伪造数据(但是无法避免代理获取信息, 具体见
ssh-代理中使用 https 以及二级代理的介绍.

引用网络上的一个说法, 将证书, 公钥, 私钥按照如下进行比喻:

  • CA: certificate authority–工商局
  • 颁发证书机构: 制作证书, 认证证书, 提供技术帮助工商局验证执照的真伪, 比如 IE, Chrome, Firefox 都存在内置证书
  • crt 证书: 营业执照, 其中身份证相当于证书

这个比喻虽然不太恰当, 但是一定程度上说明了证书机构的用途, 整个 TLS 流程如下:

  1. 浏览器请求一个安全的页面(https)
  2. WEB 服务器返回它的公钥和证书
  3. 浏览器通过可信的根 CA 检查证书是由可信的机构颁发: 证书仍然有效并且证书与被访问的网站相关
  4. 浏览器使用公钥来加密一个随机的对称密钥(注意, 这里随机对称密钥), 加上加密后的 URL 和其它加密后的 http 数据一起发回至服务器
  5. WEB 服务器使用私钥解密对称密钥, 并用它来解密在浏览器上加密了的 URL 和 http 数据
  6. WEB 服务器使用对称密钥加密请求的 HTML 文档和 http 数据并发回至浏览器
  7. 浏览器使用对称密钥解密 HTML 文档和 http 数据并展示给用户

术语和文件

证书标准以及编码格式, 其中 pem 参考web 免费证书配置.

证书的文件扩展名, 注意, 以 pem/der 编码格式的文件不一定以.pem, .der为文件扩展名, 两种编码格式:

  • pem: Privacy Enhanced Mail, 一种对证书的编码格式, 使用 Base64 编码证书, 应用于 Apache/Nginx
  • der: Distinguished Encoding Rules, 一种对证书的编码格式, 使用二进制编码证书, 应用于 Java 环境/Windows 服务器

其中 pem 可以直接查看, der 需要使用一定的命令进行查看原始内容, 两者可以互相转化:

1
2
3
4
5
6
7
# PEM存储的是以-----BEGIN开头, -----END结尾的 BASE64 编码的内容, 可以直接查看, 当然, 也可以使用命令查看证书信息
openssl x509 -in certificate.pem -text -noout
# 查看der的是二进制文件, 不能直接查看, 需要使用命令来查看证书信息
openssl x509 -in certificate.der -inform der -text -noout
# 两种编码格式的证书转换
openssl x509 -in cert.crt -outform der -out cert.der
openssl x509 -in cert.crt -inform der -outform pem -out cert.pem

虽然, 证书就两种编码格式, 但是考虑到系统等原因, 很多证书的文件扩展名并非以.pem, der结尾, 而且不同的扩展名格式的证书
中的内容还是有一些细小的区别, 当然, 他们之间还是可以相互转化的:

  • crt: certificate, 存放证书, 常见于 Unix 系统, 大部分是 pem 编码, 但也有可能是 der 编码, 可以使用上面的命令查看具体编码
  • cer: certificate, 存放证书, 常见于 Windows 系统, 大部分为 der 编码, 但也可能是 pem 编码, 可以使用上面的命令查看具体编码
  • key: 存放密钥: 公钥, 私钥, 并非存放 X.509 证书(重点), 可能为 pem 编码, 有可能是 der 编码, 查看 key 的方法见下面
  • csr: Certificate Signing Request, 证书签名请求, 并非证书或者密钥, 而是保存获取签名证书申请的各类信息, 包含一个公钥信息
  • PFX/P12: predecessor of PKCS#12, 包含公钥和私钥的二进制格式证书, 具体说明见下面
  • p7b: 以树状展示证书链(certificate chain), 也支持单个证书, 不包含私钥信息

查看 key 的命令如下:

1
2
3
4
# pem格式
openssl rsa -in mykey.key -text -noout
# der格式(下面的所有其他扩展名查看命令都是类似, PEM/DER)
openssl rsa -in mykey.key -text -noout -inform der

对于csr扩展名文件, 该文件存放着”向权威证书颁发机构获得签名证书的申请”时的公钥, 附加信息, 一般在生成整个扩展名
文件的同时, 也会生成另外一个私钥文件, 例如 IOS 开发中向苹果申请开发者证书, 查看 csr 文件内容:

1
2
openssl req -noout -text -in my.csr
openssl req -noout -text -in my.csr --inform der

对于 PFX/P12 格式的用途, 一般情况下, UNIX 系统中 CRT(特指证书)/KEY 都是分开存放在不同的文件中的, Windows 的 IIS 则将 CER/KEY 存在
一个 PFX 文件中, 如果想从 PFX 中提取信息, 需要提供提取密码, 类似一个证书密钥库, FPX 相关转化和生成命令:

1
2
3
4
5
6
7
8
9
10
# FPX 转为PEM, 此时需要输入"提取码", 最后生成pem可读公钥/私钥信息
openssl pkcs12 -in for-iis.pfx -out for-iis.pem -nodes
# 生成FPX, 将证书和私钥存放到fpx中
openssl pkcs12 -export -in certificate.crt -inkey privateKey.key -out certificate.pfx
# 从fpx中导出证书和密钥
openssl pkcs12 -in example.cn.ssl.pfx -nocerts -nodes -out example.key
openssl pkcs12 -in example.cn.ssl.pfx -clcerts -nokeys -out example.crt
# 查看信息内容(参考上面)
openssl pkcs12 -in for-iis.pfx -text -noout
openssl pkcs12 -in for-iis.pfx -text -noout -inform der

其他术语介绍:

  • X.509: 证书标准, 定义了证书应该包含哪些内容, 参考 RFC5280, SSL 就是使用该证书标准

关于证书命令, 见下面的例子.

SAN

SAN(Subject Alternative Name), SSL 标准 x509 中定义的一个扩展. 使用了SAN的 SSL 证书, 可以扩展
该证书支持的域名, 从而实现如下功能: 一个证书支持不同域名的解析.

一般使用该证书的都是大厂, 并且这些网络上有很多指向该厂其他域名的域名链接, 例如www.youtube.com.
一般不会使用到 SAN 证书文件, 这里就不阐述 SAN 扩展的证书命令.

Common Name

Common Name, 公共名, 填写你将要申请 SSL 证书的域名子域名(Subdomain).

CA 证书由: 域名, 公司信息, 序列号, 签名信息组成, 当访问 HTTPS 页面时, 浏览器会主动的校验证书信息是否
匹配, 即验证上述 4 个信息以检查证书是否有效.

在 2017 年之前 Chrome 浏览器通过CommonName来对自检证书进行绑定域名以及 IP 的检查, 但是在 2017 之后,
改为使用subjectAltName来绑定域名和 IP, 其中SubjectAltName就表示SAN, 具体见:
chrome subjectAltName

Configure

Add Root CA

通过命令来添加根证书到当前系统级别的证书中, 以便后续浏览器能够识别该证书.

MacOS

MAC OS 下, 需要将证书添加到keychain

1
2
3
4
5
6
7
8
# 添加证书到钥匙串中, 并且需要设置证书信任
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain /path/rootCA.pem
# 获取当前所有证书
security find-certificate -a
# 判断某一个证书是否在keychain中, 该name也是keychain UI界面上的名称
security find-certificate -c "Test Https"
# 移除某一个证书
sudo security delete-certificate -c "Test Https"

Windows

Windows 下, 使用自带命令 certutil 来将证书添加到系统中

1
2
3
4
# 添加证书
certutil -addstore -f "ROOT" e:/path/rootCA.pem
# 删除证书
certutil -delstore "ROOT" serial-number-hex

ubuntu

Ubuntu 下, 通过拷贝和update-ca-certificates来更新证书

1
2
3
4
5
6
# 添加证书
sudo cp rootCA.pem /usr/local/share/ca-certificates/
sudo update-ca-certificates
# 删除证书
su rm /usr/local/share/ca-certificates/rootCA.pem
sudo update-ca-certificates --fresh

centos

Centos 下, 使用update-ca-trust来更新证书

1
2
3
4
5
6
7
8
# 添加证书
yum install ca-certificates
sudo update-ca-trust force-enable
sudo cp rootCA.pem /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust extract
# 移除证书
sudo rm /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust extract

Show CA

在 3.2 节已经简单介绍了证书的编码和各个不同扩展名的含义, 以及一些命令, 这里会将所有相关扩展名的证书查看命令列出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看证书信息, 扩展名可能为: cer, crt, pem, der, 注意格式为"x509"
openssl x509 -in certificate.pem -text -noout`
openssl x509 -in certificate.der -inform der -text -noout`

# 查看密钥文件信息, 注意格式为"rsa"
openssl rsa -in mykey.key -text -noout
openssl rsa -in mykey.key -inform der -text -noout

# 查看csr(证书签名请求), 注意这个格式是"req"
openssl req -noout -text -in my.csr
openssl req -noout -text -in my.csr -inform der

# 查看pfx/p12, 注意格式为"pckcs12"
openssl pkcs12 -noout -text -in my.pfx
openssl pkcs12 -noout -text -in my.pfx -inform der

Transform CA

PEM 转为 DER 证书: openssl x509 -in cert.crt -outform der -out cert.der

DER 转为 PEM 证书: openssl x509 -in cert.crt -inform der -outform pem -out cert.pem

PFX 转为 PEM 证书:

1
2
3
4
# 转换
openssl pkcs12 -in for-iis.pfx -out for-iis.pem -nodes
# 生成PFX(需要crt, key, 根证书)
openssl pkcs12 -export -in certificate.crt -inkey privateKey.key -out certificate.pfx -certfile CACert.crt

Example

生成证书

步骤 1: 生成根证书, 利用RSA-2048密钥文件rootCA.key来生成根证书rootCA.pem, 并对该文件进行加密:

1
2
3
4
# a 生成根证书密钥文件, 并指定密码, 确保每次使用该KEY生成根证书时都需要输入密码以确保安全, 假设密码为: 123
openssl genrsa -des3 -out rootCA.key 2048
# b 根据密钥文件生成根证书(需要密码), 同时输入证书相关的 FQDN 信息
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem

上面的步骤完成之后, 生成了两个文件: rootCA.key rootCA.pem

步骤 2: 将根证书加入到 MAC钥匙串访问链中, 并添加始终信任, 这个在自建证书中充当民选政府的功能.

1
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain /path/rootCA.pem

生成 SAN 证书

步骤 1: 生成某一个特定域的域证书, 这里会创建localhost用于本地自检开发, 这里通过OpenSSL配置
文件来导入一些选项或者配置, 文件为server.csr.cnf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn

[dn]
C=US
ST=RandomState
L=RandomCity
O=RandomOrganization
OU=RandomOrganizationUnit
emailAddress=hello@example.com
CN = localhost

创建v3.ext文件, 最终搭配server.csr.cnf来生成X509 V3标准的证书, 相当于调料, 好吃的哦.

1
2
3
4
5
6
7
8
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
# 这里就是SAN中的各种域名
DNS.1 = localhost

好了, 主材和调料都已经准备了, 仿照根证书的步骤, 先生成一个证书的私钥: server.key,
证书公钥的中间文件:server.csr, 注意这里已经生成一个私钥了.

1
openssl req -new -sha256 -nodes -out server.csr -newkey rsa:2048 -keyout server.key -config <(cat server.csr.cnf)

步骤 2: 利用v3.ext, server.csr民选政府根证书一起签一个合同, 生成符合X509 V3标准的域证书:server.crt,
生成域证书的公钥, 注意, 这里有民选政府的参与哦:

1
openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out server.crt -days 500 -sha256 -extfile v3.ext

完整上面步骤之后, 生成了私钥文件: server.key, 公钥:server.crt, 第三方认证机构: 本地 MAC 钥匙串中的 rootCA.pem 文件.

参考: