简介
OpenSSL 是一款自由开源的加密库, 提供了一些命令行工具来处理数字证书. 其中的一些工 具可以作为证书权威机构来使用.
证书权威(CA)是一个认证证书实体的证书机构. 许多 Web 站点需要让他们的客户清楚他们 的连接是安全的, 他们通过向一些国际性的可信 CA(eg. VeriSign, DigiCert)为他们的站 点去购买一个证书.
在一些时候, 相比于去购买一个证书,更需要去实现一自己的 CA. 通常是需要内部网络使用 的安全连接, 或者是需要向客户发布一个证书来让他们通过服务器的认证(eg, Apache, OpenVPN)
创建 root pair
成为一个 CA 意味着需要处理加密密钥对, 私钥和证书. 首先需要第一步创建的是 root pair. 它包含 root key(ca.key.pem)和 root certificate(ca.cert.pem). 这对迷药就是 CA 的身份认证.
通常, root CA 不会给任何服务器或客户端签名. root CA 只被用来创建更多的二级 CA, 二级 CA 被 root CA 签名, 作为 root CA 的代表. 这是最佳实践, 可以让 root key 保持 离线和尽量少的被使用, 以保证 root key 有最小的泄漏风险.
⚠️注意
最佳实践是在一个安全的环境里创建root pair. 理想情况下, 在一个完全保密的环境, 并且和互联网完全隔离, 并拔除无线和有线网卡.
准备目录
选择目录来保存所有的 keys 和 certificates
# mkdir /root/ca
创建目录结构. 其中 index.txt
和 serial
文件是用来保存已经签名证书的记录的文 件数据库.
# cd /root/ca
# mkdir certs crl newcerts private
# chmod 700 private
# touch index.txt
# echo 1000 > serial
准备配置文件
我们需要创建一个 OpenSSL 配置文件来使用. 复制 root CA 的配置文件到 /root/ca/openssl.cnf
.
root CA 配置文件
# OpenSSL root CA configuration file.
# Copy to `/root/ca/openssl.cnf`.
[ ca ]
# `man ca`
default_ca = CA_default
[ CA_default ]
# Directory and file locations.
dir = /root/ca
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand
# The root key and root certificate.
private_key = $dir/private/ca.key.pem
certificate = $dir/certs/ca.cert.pem
# For certificate revocation lists.
crlnumber = $dir/crlnumber
crl = $dir/crl/ca.crl.pem
crl_extensions = crl_ext
default_crl_days = 30
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 375
preserve = no
policy = policy_strict
[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
# Options for the `req` tool (`man req`).
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
# Extension to add when the -x509 option is used.
x509_extensions = v3_ca
[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
# Optionally, specify some defaults.
countryName_default = GB
stateOrProvinceName_default = England
localityName_default =
0.organizationName_default = Alice Ltd
organizationalUnitName_default =
emailAddress_default =
[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always
[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
其中 [ca]
部分是必须的. 这里我们告诉 OpenSSL 使用选项 [CA_default]
部分
[ ca ]
# `man ca`
default_ca = CA_default
而 [CA_default]
部分包含一类设置配置. 确保之前配置的目录 /root/ca
有效
[ CA_default ]
# Directory and file locations.
dir = /root/ca
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand
# The root key and root certificate.
private_key = $dir/private/ca.key.pem
certificate = $dir/certs/ca.cert.pem
# For certificate revocation lists.
crlnumber = $dir/crlnumber
crl = $dir/crl/ca.crl.pem
crl_extensions = crl_ext
default_crl_days = 30
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 375
preserve = no
policy = policy_strict
我们应用 policy_strict
到所有的 root CA 签名, 使 root CA 仅被用来创建二级 CA.
[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
我们应用 policy_loose
到所有二级 CA 签名, 二级 CA 会给所有的 Server 和 Client 签名, 它们会有很多的种类变化.
[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[req]
部分会被使用到所有的证书请求和证书创建
[ req ]
# Options for the `req` tool (`man req`).
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
# Extension to add when the -x509 option is used.
x509_extensions = v3_ca
[req_distinguished_name]
部分包含了一般证书请求签名信息. 可以手动添加一些默认 值来配置.
[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
# Optionally, specify some defaults.
countryName_default = GB
stateOrProvinceName_default = England
localityName_default =
0.organizationName_default = Alice Ltd
#organizationalUnitName_default =
#emailAddress_default =
之后的几个部分是一些扩展, 这些扩展可以在证书签名的时候使用. 例如: 使用 -extensions v3_ca
命令行参数会应用在 [v3_ca]
下的选项.
在创建根证书的时候, 我们使用 v3_ca
[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
在创建二级 CA 时, 使用 v3_intermediate_ca
, 其中额外增加了 pathlen:0
来确保二 级 CA 下可以再创建 CA
[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
在签发客户端证书时, 我们使用 usr_cert
, 这些被使用做远程用户认证.
[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
在创建服务器证书时, 使用 server_cert
选项, 这些被用于 Web 服务器.
[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
在创建证书废除列表时, crl_ext
选项会被自动应用
[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always
在签名在线证书状态协议(Online Certificate Status Protocol (OCSP))证书时, 使用选 项 ocsp
[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
创建 root key
创建 root key( ca.key.pem
)并保证它的绝对安全. 任何拥有 root key 的人都可以创 建受信任的证书. 使用 AES 256-bit 来加密 root key, 并创建一个健壮的密码.
⚠️注意
使用4096位创建所有的根CA和二级CA的keys.
你仍然可以使用更短的长度来创建服务器和客户端证书.
# cd /root/ca
# openssl genrsa -aes256 -out private/ca.key.pem 4096
Enter pass phrase for ca.key.pem: secretpassword
Verifying - Enter pass phrase for ca.key.pem: secretpassword
# chmod 400 private/ca.key.pem
创建根证书(Root certificate)
使用 root key(ca.key.pem)来创建根证书(ca.cert.pem). 给根证书设置一个比较长的有效 期, 比如 20 年. 一旦根证书失效, 所有被根证书签名的证书都会失效.
⚠️警告
当使用`req`工具时, 必须使用`-config`选项来指定一个配置文件, 否则OpenSSL会默认使用`/etc/pki/tls/openssl.cnf`
# cd /root/ca
# openssl req -config openssl.cnf \
-key private/ca.key.pem \
-new -x509 -days 7300 -sha256 -extensions v3_ca \
-out certs/ca.cert.pem
Enter pass phrase for ca.key.pem: secretpassword
You are about to be asked to enter information that will be incorporated
into your certificate request.
-----
Country Name (2 letter code) [XX]:GB
State or Province Name []:England
Locality Name []:
Organization Name []:Alice Ltd
Organizational Unit Name []:Alice Ltd Certificate Authority
Common Name []:Alice Ltd Root CA
Email Address []:
# chmod 444 certs/ca.cert.pem
验证根证书
# openssl x509 -noout -text -in certs/ca.cert.pem
输出会显示
Signature Algorithm
签名算法Validity
证书的有效期Public-Key
公钥长度Issuer
, 签发证书的实体Subject
, 指向证书自己
当 Issuer
和 Subject
相同时, 说明证书是自签名的. 明确所有根证书都是自签名的.
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=GB, ST=England,
O=Alice Ltd, OU=Alice Ltd Certificate Authority,
CN=Alice Ltd Root CA
Validity
Not Before: Apr 11 12:22:58 2015 GMT
Not After : Apr 6 12:22:58 2035 GMT
Subject: C=GB, ST=England,
O=Alice Ltd, OU=Alice Ltd Certificate Authority,
CN=Alice Ltd Root CA
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
输出还会显示 X509v3 extensions. 我们创建证书时应用的选项 v3_ca
, 所以 [v3_ca]
下的配置项会被反映出来.
X509v3 extensions:
X509v3 Subject Key Identifier:
38:58:29:2F:6B:57:79:4F:39:FD:32:35:60:74:92:60:6E:E8:2A:31
X509v3 Authority Key Identifier:
keyid:38:58:29:2F:6B:57:79:4F:39:FD:32:35:60:74:92:60:6E:E8:2A:31
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Key Usage: critical
Digital Signature, Certificate Sign, CRL Sign
创建二级 CA, intermediate pair
二级 CA 作为 Root CA 代表的实体. Root CA 签署中间证书, 来达成一个信任链.
使用二级 CA 的主要目的是为了安全. 这样 root key 可以被保存在一个离线环境, 并尽可 能少的被使用. 如果二级 CA 的 key 泄漏, root CA 可以废弃二级 CA 证书并创建一个新 的二级密钥对.
准备目录
Root CA 文件保存在目录 /root/ca
下. 选择一个不同的目录( /root/ca/intermediate
)来保存二级 CA 文件
# mkdir /root/ca/intermediate
创建和 root CA 相同的目录结构来保存文件. 增加了一个新的目录 csr
来保存证书签名 请求
# cd /root/ca/intermediate
# mkdir certs crl csr newcerts private
# chmod 700 private
# touch index.txt
# echo 1000 > serial
添加一个 crlnumber
文件到二级 CA 目录树. 使用 crlnumber
来对证书废除列表 (certificate revocation lists)进行追踪.
# echo 1000 > /root/ca/intermediate/crlnumber
复制二级 CA 配置文件到 /root/ca/intermediate/openssl.cnf
文件.
二级 CA 配置文件内容:
# OpenSSL intermediate CA configuration file.
# Copy to `/root/ca/intermediate/openssl.cnf`.
[ ca ]
# `man ca`
default_ca = CA_default
[ CA_default ]
# Directory and file locations.
dir = /root/ca/intermediate
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand
# The root key and root certificate.
private_key = $dir/private/intermediate.key.pem
certificate = $dir/certs/intermediate.cert.pem
# For certificate revocation lists.
crlnumber = $dir/crlnumber
crl = $dir/crl/intermediate.crl.pem
crl_extensions = crl_ext
default_crl_days = 30
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 375
preserve = no
policy = policy_loose
[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
# Options for the `req` tool (`man req`).
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
# Extension to add when the -x509 option is used.
x509_extensions = v3_ca
[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
# Optionally, specify some defaults.
countryName_default = GB
stateOrProvinceName_default = England
localityName_default =
0.organizationName_default = Alice Ltd
organizationalUnitName_default =
emailAddress_default =
[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always
[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning
相对于 root CA, 有 5 个选项发生了变化
[ CA_default ]
dir = /root/ca/intermediate
private_key = $dir/private/intermediate.key.pem
certificate = $dir/certs/intermediate.cert.pem
crl = $dir/crl/intermediate.crl.pem
policy = policy_loose
创建二级 CA 的 Key
创建二级 CA 的 key( intermediate.key.pem
) 使用 AES 256-bit 来加密并设置强密码 .
# cd /root/ca
# openssl genrsa -aes256 \
-out intermediate/private/intermediate.key.pem 4096
Enter pass phrase for intermediate.key.pem: secretpassword
Verifying - Enter pass phrase for intermediate.key.pem: secretpassword
# chmod 400 intermediate/private/intermediate.key.pem
创建二级 CA 证书
使用二级 CA 的 key 来创建证书签名请求(CSR). 详细信息和 CA 大致相同. 尽管如此, Common Name 选项必须不同.
⚠️警告
确保你指定的配置文件是`intermediate/openssl.cnf`
# cd /root/ca
# openssl req -config intermediate/openssl.cnf -new -sha256 \
-key intermediate/private/intermediate.key.pem \
-out intermediate/csr/intermediate.csr.pem
Enter pass phrase for intermediate.key.pem: secretpassword
You are about to be asked to enter information that will be incorporated
into your certificate request.
-----
Country Name (2 letter code) [XX]:GB
State or Province Name []:England
Locality Name []:
Organization Name []:Alice Ltd
Organizational Unit Name []:Alice Ltd Certificate Authority
Common Name []:Alice Ltd Intermediate CA
Email Address []:
创建二级 CA 证书, 使用 root CA 签名 CSR 并使用选项 v3_intermediate_ca
. 二级证 书需要设置一个比 root CA 证书更短的有效期. 10 年是一个比较好的选项.
⚠️警告
这次, 指定root CA配置文件`/root/ca/openssl.cnf`
# cd /root/ca
# openssl ca -config openssl.cnf -extensions v3_intermediate_ca \
-days 3650 -notext -md sha256 \
-in intermediate/csr/intermediate.csr.pem \
-out intermediate/certs/intermediate.cert.pem
Enter pass phrase for ca.key.pem: secretpassword
Sign the certificate? [y/n]: y
# chmod 444 intermediate/certs/intermediate.cert.pem
index.txt
文件是 OpenSSL ca
工具用来保存证书的数据库. 不要删除或手动修改这个 文件. 现在它应该包含了二级 CA 证书的信息
V 250408122707Z 1000 unknown ... /CN=Alice Ltd Intermediate CA
验证二级 CA 证书
和验证根证书一样, 使用相同的方式来验证二级 Ca 证书的有效性.
# openssl x509 -noout -text \
-in intermediate/certs/intermediate.cert.pem
验证二级 CA 证书紧靠着根证书. 返回 OK
指示这个信任链是正确的.
# openssl verify -CAfile certs/ca.cert.pem \
intermediate/certs/intermediate.cert.pem
intermediate.cert.pem: OK
创建证书链文件
当应用(比如, web 浏览器)尝试去对二级 CA 签名的证书做验证, 它必须也验证根证书和二 级 CA 的信任链. 完成信任链, 就需要创建一个证书链来给应用.
创建证书链, 把二级 CA 证书和根证书连接起来, 我们随后会使用这个文件来演正被二级 CA 证书的签名.
# cat intermediate/certs/intermediate.cert.pem \
certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem
# chmod 444 intermediate/certs/ca-chain.cert.pem
⚠️提示
我们的证书链文件必须包含根证书, 因为当前所有的客户端应用都没雨配置这个根证书. 更好的选项是, 比如你是一个内网的管理者, 可以把根证书安装到所有需要验证的客户端. 用这种方式, 证书链文件只需要包含你的二级CA证书
签名 Server 和 Client 证书
我们接下来使用我们的二级 CA 来签名. 你可以在多种情况时使用这些签名证书, 比如创建 安全的浏览器连接, 或者客户端到 server 的认证.
⚠️注意
接下来的步骤揭示你作为certificate authority(CA). 第三方, 尽管可以自己创建自己的私钥和证书请求(CSR), 不需要把它们的私钥(private key)显示给你. 他们只想你提供CSR, 然后你签署一个签名的证书给他们. 在这种情况下, 忽略`genrsa`和`req`命令.
创建 key
我们的根 CA 和二级 CA 都是 4096bit 的. Server 和 Client 证书通常在一年内失效, 所 以我们安全的使用 2048 位密钥对.
⚠️注意
尽管4096bits略微安全于2048bits, 它会减慢TLS握手并且显著的增加握手时的处理器负载. 基于这个原因, 大多数websites都适用2048bit密钥对
如果你为一个 web 服务器(如: Apache)创建密钥对, 你需要在每次重启服务时都输入密码. 可以删除掉 -aes256
选项来创建一个没有密码的 key.
# cd /root/ca
# openssl genrsa -aes256 \
-out intermediate/private/www.example.com.key.pem 2048
# chmod 400 intermediate/private/www.example.com.key.pem
创建证书 certificate
使用私钥(private key)来创建证书请求(CSR). CSR 详情不需要匹配到二级 CA. 对 Server 证书, 配置的 Common Name 必须是一个 FQDN(full qualified domain name, 如www.example.com), 然而对 Client 证书它可以是任何唯一的识别码(如, 一个邮件地址 ). 记住 Comman Name 不能和你的根证书或二级 CA 证书相同.
# cd /root/ca
# openssl req -config intermediate/openssl.cnf \
-key intermediate/private/www.example.com.key.pem \
-new -sha256 -out intermediate/csr/www.example.com.csr.pem
Enter pass phrase for www.example.com.key.pem: secretpassword
You are about to be asked to enter information that will be incorporated
into your certificate request.
-----
Country Name (2 letter code) [XX]:US
State or Province Name []:California
Locality Name []:Mountain View
Organization Name []:Alice Ltd
Organizational Unit Name []:Alice Ltd Web Services
Common Name []:www.example.com
Email Address []:
使用二级 CA 去签名 CSR 来创建一个证书. 如果证书是被用于一个 server, 那么使用 server_cert
扩展. 如果证书时给用户做用户认证, 使用 user_cert
扩展. 证书通常 给予指定一年的有效期, 尽管通常 CA 会额外给于几天时间方便.
# cd /root/ca
# openssl ca -config intermediate/openssl.cnf \
-extensions server_cert -days 375 -notext -md sha256 \
-in intermediate/csr/www.example.com.csr.pem \
-out intermediate/certs/www.example.com.cert.pem
# chmod 444 intermediate/certs/www.example.com.cert.pem
intermediate/index.txt
文件应该会包含一行内容指向新的证书
V 160420124233Z 1000 unknown ... /CN=www.example.com
验证证书
# openssl x509 -noout -text \
-in intermediate/certs/www.example.com.cert.pem
Issuer 就是二级 CA. Subject 就是证书自己
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=GB, ST=England,
O=Alice Ltd, OU=Alice Ltd Certificate Authority,
CN=Alice Ltd Intermediate CA
Validity
Not Before: Apr 11 12:42:33 2015 GMT
Not After : Apr 20 12:42:33 2016 GMT
Subject: C=US, ST=California, L=Mountain View,
O=Alice Ltd, OU=Alice Ltd Web Services,
CN=www.example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
输出会显示 X509v3 extensions. 当创建证书, 选择的是 server_cert
或者 usr_cert
. 这个选项的内容就会在这里被反射出来
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Cert Type:
SSL Server
Netscape Comment:
OpenSSL Generated Server Certificate
X509v3 Subject Key Identifier:
B1:B8:88:48:64:B7:45:52:21:CC:35:37:9E:24:50:EE:AD:58:02:B5
X509v3 Authority Key Identifier:
keyid:69:E8:EC:54:7F:25:23:60:E5:B6:E7:72:61:F1:D4:B9:21:D4:45:E9
DirName:/C=GB/ST=England/O=Alice Ltd/OU=Alice Ltd Certificate Authority/CN=Alice Ltd Root CA
serial:10:00
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
使用之前创建的 CA 证书链文件(ca-chain.cert.pem), 我们可以验证新的证书在被信任链 上是正确的
# openssl verify -CAfile intermediate/certs/ca-chain.cert.pem \
intermediate/certs/www.example.com.cert.pem
www.example.com.cert.pem: OK
部署证书
现在可以讲证书部署到 server, 或者发布证书给客户. 当部署到服务器应用(如, Apache) 时, 你需要确保下边的文件可用:
ca-chain.cert.pem
www.example.com.key.pem
www.example.com.cert.perm
如果你是给第三方的证书请求(CSR)做签名, 你不需要获取他们的私钥(private key), 所以 你需要返回给他们证书链文件( ca-chain.cert.pem
)和证书文件( www.example.com.cert.pem
)
证书废除列表(Certificate revocation lists)
证书废除列表(Certificate revocation lists(CRL))提供了一个证书的列表, 表明其中的 证书都是被废除的. 客户端应用, 比如 web 浏览器, 可以使用 CRL 去检查服务器真实性. 服务器应用, 比如 Apache 和 OpenVPN, 可以使用 CRL 来禁止不被信任的客户端的访问.
发布 CRL 到一个可以公开访问的地方(如: http://example.com/intermediate.crl.pem). 第三方可以根据地址获取到 CRL, 他们可以根据这个来检测他们依赖的证书是否被废除.
⚠️注意
一些应用废除了CRLs, 他们使用在线证书状态协议(Online Certificate Status Protocol (OCSP))来代替.
准备配置文件
当一个 CA 签名证书, 他们通常会写入 CRL 地址到证书里. 添加 crlDistributionPoints
到对应的部分. 在这里, 我们添加到 [server_cert]
部分中
[ server_cert ]
# ... snipped ...
crlDistributionPoints = URI:http://example.com/intermediate.crl.pem
创建 CRL
# cd /root/ca
# openssl ca -config intermediate/openssl.cnf \
-gencrl -out intermediate/crl/intermediate.crl.pem
⚠️注意
在ca man page中的`CRL OPTIONS`部分包含了更多关于如何创建CRLs的信息
可以使用 crl
工具来检查 CRL 的内容
# openssl crl -in intermediate/crl/intermediate.crl.pem -noout -text
现在没有被吊销的证书, 所以输出是 No Revoked Certificates
.
你应该定期的重新创建 CRL. 在默认情况下, CRL 在 30 天后失效. 这个值由 [CA_default]
部分中的 default_crl_days
选项控制.
吊销证书
通过一个例子来看看这个过程. Alice 有一个 web 服务器和一个私有的目录存放一些暖心 的可爱小猫图片. Alice 想授权她的朋友 Bob 来访问这个集合.
Bob 创建了一个私钥和证书请求文件 CSR
$ cd /home/bob
$ openssl genrsa -out bob@example.com.key.pem 2048
$ openssl req -new -key bob@example.com.key.pem \
-out bob@example.com.csr.pem
You are about to be asked to enter information that will be incorporated
into your certificate request.
-----
Country Name [XX]:US
State or Province Name []:California
Locality Name []:San Francisco
Organization Name []:Bob Ltd
Organizational Unit Name []:
Common Name []:bob@example.com
Email Address []:
Bob 发送他的 CSR 给 Alice, Alice 给他签名.
# cd /root/ca
# openssl ca -config intermediate/openssl.cnf \
-extensions usr_cert -notext -md sha256 \
-in intermediate/csr/bob@example.com.csr.pem \
-out intermediate/certs/bob@example.com.cert.pem
Sign the certificate? [y/n]: y
1 out of 1 certificate requests certified, commit? [y/n]: y
Alice 验证证书有效
# openssl verify -CAfile intermediate/certs/ca-chain.cert.pem \
intermediate/certs/bob@example.com.cert.pem
bob@example.com.cert.pem: OK
index.txt
文件包含一个新的连接
V 160420124740Z 1001 unknown ... /CN=bob@example.com
Alice 发送证书给 Bob. Bob 安装证书到浏览器, 现在可以访问到 Alice 的小猫图片.
坏事, 随着 Bob 的不端行为而来. Bob 把 Alice 的小猫图片发送到了 Hack News, 说了他 是这些的拥有者, 并获得了大量的赞. Alice 发现了这事摒弃要立即吊销他的访问权限.
# cd /root/ca
# openssl ca -config intermediate/openssl.cnf \
-revoke intermediate/certs/bob@example.com.cert.pem
Enter pass phrase for intermediate.key.pem: secretpassword
Revoking Certificate 1001.
Data Base Updated
index.txt
中 Bob 的证书这行开始现在使用字符 R
标示, 这表示证书已经被吊销 (Revoked).
R 160420124740Z 150411125310Z 1001 unknown ... /CN=bob@example.com
在吊销了 Bob 的证书后, Alice 必须重新创建 CRL
服务端使用 CRL
对于客户端证书, 一般时候服务器应用(如, Apache)来进行验证. 服务应用需要可以访问 CRL.
在 Alice 的例子中, 他可以添加 SSLCARevocationPath
直接到她的 Apache 配置文件中 并复制 CRL 到她的 web 服务器. 下次 Bob 再进行访问时, Apache 会检查他的证书存在于 CRL 中并禁止访问.
相似的, OpenVPN 也使用 crl-verify
指向了被禁用的客户端证书.
客户端使用 CRL
对于服务器证书, 一般是由客户端应用(如,浏览器)来进行验证. 这时, 应用必须可以远程 访问 CRL.
如果证书被签名的扩展中包含了 crlDistributionPoints
, 客户端应用能够根据地址读取 到 CRL 信息.
CRL 地址信息可以在证书的 x509v3 详情中看到.
# openssl x509 -in cute-kitten-pictures.example.com.cert.pem -noout -text
X509v3 CRL Distribution Points:
Full Name:
URI:http://example.com/intermediate.crl.pem
在线证书状态协议 (Online Certificate Status Protocol)
在线证书状态协议 (Online Certificate Status Protocol)(OCSP) 被创建用于替代证书吊 销列表(CRL). 和 CRLs 相似, OCSP 运行访问查询出证书的吊销状态.
当服务器签名证书时, 他们一般会包含一个 OSCP 服务器地址(如, http://ocsp.example.com)在证书中. 这个功能和 CRL 的 crlDistributionPoints
功能 作用相似.
示例, 当 web 浏览器接受到一个服务器证书, 它立即想请求证书中的 OSCP 服务器地址. 在这个地址中, OCSP 响应程序监听请求和响应证书的吊销状态.
⚠️注意
虽然推荐尽可能的使用OCSP, 尽管实际上你应该趋向于只需要OCSP来给web站点证书. 一些web浏览器已经废弃或移除了对CRL的支持.
准备配置文件
要使用 OCSP, CA 必须要编码 OCSP 服务器地址到签名的证书中. 使用 authorityInfoAccess
选项到合适的部分, 在这里应该是 [server_cert]
部分
[ server_cert ]
# ... snipped ...
authorityInfoAccess = OCSP;URI:http://ocsp.example.com
创建 OCSP 密钥对
OCSP 响应程序必须要一个加密密钥对来签名发送给请求的响应内容. OSCP 密钥对必须由和 证书签名相同的 CA 签名.
创建私钥并使用 AES-256 加密
# cd /root/ca
# openssl genrsa -aes256 \
-out intermediate/private/ocsp.example.com.key.pem 4096
创建证书签名请求 CSR. 详细信息默认需要和签名 CA 相同. Common Name, 需要是 FQDN.
# cd /root/ca
# openssl req -config intermediate/openssl.cnf -new -sha256 \
-key intermediate/private/ocsp.example.com.key.pem \
-out intermediate/csr/ocsp.example.com.csr.pem
Enter pass phrase for intermediate.key.pem: secretpassword
You are about to be asked to enter information that will be incorporated
into your certificate request.
-----
Country Name (2 letter code) [XX]:GB
State or Province Name []:England
Locality Name []:
Organization Name []:Alice Ltd
Organizational Unit Name []:Alice Ltd Certificate Authority
Common Name []:ocsp.example.com
Email Address []:
使用 CA 签署 CSR
# openssl ca -config intermediate/openssl.cnf \
-extensions ocsp -days 375 -notext -md sha256 \
-in intermediate/csr/ocsp.example.com.csr.pem \
-out intermediate/certs/ocsp.example.com.cert.pem
验证证书的 x509v3 extensions 正确性
# openssl x509 -noout -text \
-in intermediate/certs/ocsp.example.com.cert.pem
X509v3 Key Usage: critical
Digital Signature
X509v3 Extended Key Usage: critical
OCSP Signing
吊销证书
OpenSSL 的 ocsp
工具实现了一个 OCSP responder, 但只为了做测试使用. 生产级别的 OCSP responder 也有, 但是超越了这个指引的范围.
创建一个 server 证书测试.
# cd /root/ca
# openssl genrsa -out intermediate/private/test.example.com.key.pem 2048
# openssl req -config intermediate/openssl.cnf \
-key intermediate/private/test.example.com.key.pem \
-new -sha256 -out intermediate/csr/test.example.com.csr.pem
# openssl ca -config intermediate/openssl.cnf \
-extensions server_cert -days 375 -notext -md sha256 \
-in intermediate/csr/test.example.com.csr.pem \
-out intermediate/certs/test.example.com.cert.pem
在 localhost
上运行 OCSP responder . 有别于 CRL 保存吊销状态于各个文件中, OCSP responder 直接读取 index.txt
. 响应被 OCSP 密钥对签名(使用 -rkey
和 -rsigner
选项)
# openssl ocsp -port 127.0.0.1:2560 -text -sha256 \
-index intermediate/index.txt \
-CA intermediate/certs/ca-chain.cert.pem \
-rkey intermediate/private/ocsp.example.com.key.pem \
-rsigner intermediate/certs/ocsp.example.com.cert.pem \
-nrequest 1
Enter pass phrase for ocsp.example.com.key.pem: secretpassword
在另一个终端中, 发送一个请求给 OCSP responder. 指定的 -cert
选项指定了请求的证 书.
# openssl ocsp -CAfile intermediate/certs/ca-chain.cert.pem \
-url http://127.0.0.1:2560 -resp_text \
-issuer intermediate/certs/intermediate.cert.pem \
-cert intermediate/certs/test.example.com.cert.pem
开始的输出显示如下:
- 是否接收到成功的响应 (OCSP Response Status)
- responder 的身份 (Responder Id)
- 证书的吊销状态 (Cert Status)
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response
Version: 1 (0x0)
Responder Id: ... CN = ocsp.example.com
Produced At: Apr 11 12:59:51 2015 GMT
Responses:
Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: E35979B6D0A973EBE8AEDED75D8C27D67D2A0334
Issuer Key Hash: 69E8EC547F252360E5B6E77261F1D4B921D445E9
Serial Number: 1003
Cert Status: good
This Update: Apr 11 12:59:51 2015 GMT
吊销证书
# openssl ca -config intermediate/openssl.cnf \
-revoke intermediate/certs/test.example.com.cert.pem
Enter pass phrase for intermediate.key.pem: secretpassword
Revoking Certificate 1003.
Data Base Updated
之后, 运行 OCSP responder 并在另一个终端中发请求. 这次, 输出会显示 Cert Status: revoked
和 Revocation Time
.
OCSP Response Data:
OCSP Response Status: successful (0x0)
Response Type: Basic OCSP Response
Version: 1 (0x0)
Responder Id: ... CN = ocsp.example.com
Produced At: Apr 11 13:03:00 2015 GMT
Responses:
Certificate ID:
Hash Algorithm: sha1
Issuer Name Hash: E35979B6D0A973EBE8AEDED75D8C27D67D2A0334
Issuer Key Hash: 69E8EC547F252360E5B6E77261F1D4B921D445E9
Serial Number: 1003
Cert Status: revoked
Revocation Time: Apr 11 13:01:09 2015 GMT
This Update: Apr 11 13:03:00 2015 GMT