简介

OpenSSL 是一个免费开源的加密库,它提供了多个用于处理数字证书的命令行工具。其中一些工具可以用作证书颁发机构。

创建跟对

作为证书颁发机构 (CA),意味着要处理私钥和公钥的加密对。我们将创建的第一个加密对是根密钥对。它由根密钥 ( ca.key.pem) 和根证书 ( ca.cert.pem) 组成。该密钥对构成了您的 CA 的身份标识。

通常情况下,根证书颁发机构 (CA) 不会直接签署服务器或客户端证书。根 CA 仅用于创建一个或多个中间 CA,这些中间 CA 受根 CA 信任,代表根 CA 签署证书。这是最佳实践。它允许根密钥尽可能保持离线状态且不使用,因为根密钥的任何泄露都将造成灾难性后果。

准备目录

mkdir /root/ca/
cd /root/ca/
mkdir certs crl newcerts private
chmod 700 private
touch index.txt
echo 1000 > serial

准备配置文件

您必须为 OpenSSL 创建配置文件。将根配置文件复制 到/root/ca/openssl.cnf. 此部分为必填项。在这里,我们告诉 OpenSSL 使用该部分中的选项。[ ca ][ 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所有根 CA 签名,因为根 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 会对可能来自各种第三方的服务器和客户端证书进行签名。

[ 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>.
commonName                      = Common Name
countryName                     = Country Name (2 letter code)
stateOrProvinceName             = State or Province Name
localityName                    = Locality Name
0.organizationName              = Organization Name
organizationalUnitName          = Organizational Unit 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

v3_ca_intermediate我们将在创建中间证书时应用此扩展。 pathlen:0这确保中间 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, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage       = serverAuth

创建证书吊销列表crl_ext时,会自动应用此扩展。

[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier = keyid:always

我们将ocsp在签署在线证书状态协议 (OCSP)证书时应用此扩展。

[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints       = CA:FALSE
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid,issuer
keyUsage               = critical, digitalSignature
extendedKeyUsage       = critical, OCSPSigning

创建根秘钥

创建根密钥(ca.key.pem)并妥善保管。任何持有根密钥的人都可以颁发受信任的证书。使用 AES 256 位加密和强密码对根密钥进行加密。

所有根证书和中间证书颁发机构密钥均使用 4096 位。您仍然可以签署长度较短的服务器和客户端证书。

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

创建根证书

使用根密钥(ca.key.pem)创建根证书(ca.cert.pem)。将根证书的有效期设置为较长的​​期限,例如二十年。根证书过期后,所有由该 CA 签发的证书都将失效。

警告:每次使用 req 工具时,必须使用选项指定要使用的配置文件-config,否则 OpenSSL 将使用默认配置文件/etc/pki/tls/openssl.cnf。

cd /root/ca
openssl req -config openssl.conf -key private/ca.key.pem -new -x509 -days 1825 -sha256 -extensions v3_ca -out certs/ca.cert.pem
chmod 444 certs/ca.cert.pem

验证根证书

openssl x509 -noout -text -in certs/ca.cert.pem

输出结果显示:

  • 使用的Signature Algorithm

  • 证书日期Validity

  • 比特Public-Key长度

  • 即Issuer签署该证书的实体

  • 指Subject的是证书本身。

由于证书是自签名证书,因此Issuer两者Subject完全相同。请注意,所有根证书都是自签名证书。

输出结果还显示了X509v3 扩展。我们应用了 v3_ca 扩展,因此其选项应该反映在输出结果中。

创建中间对

中间证书颁发机构(CA)是可以代表根CA签署证书的实体。根CA签署中间证书,从而形成信任链。

使用中间 CA 的主要目的是为了安全。根密钥可以离线保存,并尽可能减少使用频率。如果中间密钥泄露,根 CA 可以撤销该中间证书,并创建一个新的中间加密对。

准备中间目录

根 CA 文件保存在/root/ca。请选择不同的目录(/root/ca/intermediate)来存储中间 CA 文件。

mkdir /root/ca/intermediate

在这个例子中,中间文件夹位于/root/ca目录下。这只是为了方便起见,而且,这被认为是一种不好的做法:根 CA 和中间 CA 应该位于不同的机器上。

创建与根 CA 文件相同的目录结构。最好再创建一个 csr 目录来存放证书签名请求。

cd /root/ca/intermediate
mkdir certs crl csr newcerts private
chmod 700 private
touch index.txt
echo 1000 > serial

crlnumber向中间 CA 目录树添加一个文件。crlnumber该文件用于跟踪证书吊销列表。

echo 1000 > crlnumber

将中间配置文件复制 到指定位置/root/ca/intermediate/openssl.cnf。与根 CA 配置文件相比,有六个选项已更改:

[ 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
copy_extensions = copy

创建中间键

创建中间密钥(intermediate.key.pem)。使用 AES 256 位加密和强密码对中间密钥进行加密。

openssl genrsa -aes256 -out intermediate/private/intermediate.key.pem 4096

chmod 400 intermediate/private/intermediate.key.pem

创建中间证书

使用中间密钥创建证书签名请求 (CSR)。其详细信息通常应与根 CA 的信息一致。但是,通用名称必须不同。

确保您指定中间 CA 配置文件(intermediate/openssl.cnf)。

openssl req -config intermediate/openssl.conf -new -sha256 -key intermediate/private/intermediate.key.pem -out intermediate/csr/intermediate.csr.pem

要创建中间证书,请使用带有v3_intermediate_ca扩展名的根 CA 对中间 CSR 进行签名。中间证书的有效期应短于根证书,十年较为合理。

这次,指定根CA配置文件

openssl ca -config openssl.conf -extensions v3_intermediate_ca -days 1460 -notext -md sha256 in intermediate/csr/intermediate.csr.pem -out intermediate/certs/intermediate.certs.pem

OpenSSL 工具将证书数据库存储在该index.txt文件中ca。请勿手动删除或编辑此文件。该文件现在应该包含一行指向中间证书的信息。

核实中级证书

与检查根证书一样,检查中间证书的详细信息是否正确。

openssl x509 -noout -text -in intermediate/certs/intermediate.cert.pem

将中间证书与根证书进行比对。如果匹配成功,则OK表明信任链完整无损。

openssl verify -CAfile certs/ca.cert.pem intermediate/certs/intermediate.cert.pem

创建证书链文件

当应用程序(例如 Web 浏览器)尝试验证由中间 CA 签名的证书时,它还必须将该中间证书与根证书进行比对。为了完善信任链,需要创建一个 CA 证书链并将其提供给应用程序。

要创建 CA 证书链,请将中间证书和根证书连接起来。稍后我们将使用此文件来验证由中间 CA 签名的证书。

cat intermediate/certs/intermediate.cert.pem certs/ca.cert.pem > intermediate/certs/ca-chain.cert.pem

我们的证书链文件必须包含根证书,因为目前还没有任何客户端应用程序知道它。更好的做法(尤其是在管理内网的情况下)是将根证书安装到每个需要连接的客户端上。在这种情况下,证书链文件只需包含中间证书即可。

签署服务器和客户端证书

我们将使用我们的中间 CA 来签署证书。您可以在各种情况下使用这些已签名的证书,例如保护与 Web 服务器的连接或验证连接到服务的客户端身份。

以下步骤是从证书颁发机构的角度出发的。但是,第三方可以在不向您透露其私钥的情况下创建自己的私钥和证书签名请求 (CSR)。他们将 CSR 提供​​给您,您再返回一个已签名的证书。在这种情况下,请跳过 genrsaandreq命令。

创建密钥

我们的根证书和中间证书对是 4096 位。服务器和客户端证书通常在一年后过期,因此我们可以安全地使用 2048 位证书。

虽然 4096 位比 2048 位安全性略高,但它会减慢 TLS 握手速度,并显著增加握手期间的处理器负载。因此,大多数网站都使用 2048 位密钥对。

如果您要创建用于 Web 服务器(例如 Apache)的加密密钥对,则每次重启 Web 服务器时都需要输入此密码。您可能需要省略-aes256创建无密码密钥的选项。

cd /root/ca
openssl genrsa -aes256 -out intermediate/private/example.com.key.pem 2048
chmod 400 intermediate/private/example.com.key.pem

创建证书

使用私钥创建证书签名请求 (CSR)。CSR 的详细信息无需与中间 CA 匹配。对于服务器证书, 通用名称必须是完全限定域名(例如 example.com),而对于客户端证书,它可以是任何唯一标识符(例如电子邮件地址)。请注意,通用名称不能与根证书或中间证书相同。

对于服务器证书,提供主题备用名称(SAN) 扩展可能很有用(对于最新版本的浏览器而言是必需的),这样证书除了通用名称(CN ) 之外,还能对其他主机名有效。可以使用-addext开关来提供 SAN(需要 openssl 1.1.1),如下例所示。对于旧版本的 openssl,可以通过在文件中创建一个新节(例如 <section> alt_names) intermediate/openssl.cnf并在server_cert<section> 中引用它来指定 SAN。

[ server_cert ]
...
subjectAltName = @alt_names

[ alt_names ]
DNS.1          = example.com
DNS.2          = www.example.com
DNS.3          = m.example.com
为了在中间 CA 签署此 CSR 时保留此扩展,必须将其包含在部分中 。copy_extensions = copy[ CA_default ]intermediate/openssl.cnf
cd /root/ca
openssl req -config intermediate/openssl.cnf \
    -key intermediate/private/example.com.key.pem \
    -new -sha256 -out intermediate/csr/example.com.csr.pem \
    -addext "subjectAltName = DNS:example.com,DNS:www.example.com,DNS:m.example.com"
Enter pass phrase for example.com.key.pem: secretpassword
You are about to be asked to enter information that will be incorporated
into your certificate request.
-----
Common Name []:example.com
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
Email Address []:

要创建证书,请使用中间 CA 对 CSR 进行签名。如果证书将用于服务器,请使用服务器server_cert扩展名。如果证书将用于用户身份验证,请使用用户usr_cert扩展名。证书的有效期通常为一年,但 CA 通常会为了方便起见而额外延长几天。

cd /root/ca
openssl ca -config intermediate/openssl.cnf -extensions server_cert \
    -days 375 -notext -md sha256 -in intermediate/csr/example.com.csr.pem \
    -out intermediate/certs/example.com.cert.pem
chmod 444 intermediate/certs/example.com.cert.pem

该intermediate/index.txt文件应包含一行引用此新证书的信息。

V 160420124233Z 1000 unknown ... /CN=example.com

验证证书

openssl x509 -noout -text -in intermediate/certs/example.com.cert.pem

颁发者是中间证书颁发机构。主题 指的是证书本身。

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=example.com
Subject Public Key Info:
    Public Key Algorithm: rsaEncryption
        Public-Key: (2048 bit)
输出结果还会显示X509v3 扩展。创建证书时,您使用了 `<extensions>` server_cert或 ` usr_cert<extensions>` 扩展。相应配置部分的选项将反映在输出结果中。

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, Non Repudiation, Key Encipherment
X509v3 Extended Key Usage:
    TLS Web Server Authentication

X509v3 Subject Alternative Name:
    DNS:example.com, DNS:www.example.com, DNS: m.example.com

使用我们之前创建的 CA 证书链文件(ca-chain.cert.pem)来验证新证书是否具有有效的信任链。

openssl verify -CAfile intermediate/certs/ca-chain.cert.pem \
    intermediate/certs/example.com.cert.pem
example.com.cert.pem: OK

部署证书

现在您可以将新证书部署到服务器,也可以将证书分发给客户端。部署到服务器应用程序(例如 Apache)时,您需要提供以下文件:

ca-chain.cert.pem

example.com.key.pem

example.com.cert.pem

如果您要签署来自第三方的 CSR,您无法访问他们的私钥,因此您只需要将链文件(ca-chain.cert.pem)和证书(example.com.cert.pem)交还给他们。

证书包 如果您尝试以 PEM 格式导入客户端证书及其密钥,某些浏览器可能会报错,因此您需要将它们打包在一起。您甚至可以使用相应-certfile选项将其他重要证书添加到此捆绑包中。

openssl pkcs12 -export -out intermediate/certs/client.full.pfx \
    -inkey intermediate/private/client.key.pem -in intermediate/certs/client.cert.pem \
    -certfile intermediate/certs/intermediate.cert.pem -certfile certs/ca.cert.pem