第05课:用

第05课:用 OpenSSL 搭建企业内部 CA 认证中心的根证书

在一个企业的局域网内(Internet),可能有很多的 Web 服务器或者企业应用服务器,比如说基于 Tomcat、IIS、Nginx 的 Web 应用服务器,消息中间件服务器,比如 Mosquito MQTT 服务器、Rabbit MQ 服务器;或者一些目录服务器,比如 Microsoft 的 Active Directory,Sun 的目录服务器,Oracle 的 OID 目录服务器等;或者还有一些邮件服务器;都需要应用 SSL 来保护服务器和客户端之间的通信安全问题。

诚然,我们也可以为上面的这些应用生成 SSL 的证书请求,然后发送给权威的第三方 CA 供应商,比如,下面的目前世界上最知名的 8 家 SSL 证书 CA 供应商。

  • VeriSign
  • GeoTrust
  • Comodo
  • Digicert
  • Thawte
  • GoDaddy
  • Network Solutions
  • GlobalSign

但是,要知道把服务器生成的证书请求发给这些 CA 供应商去签名你的证书请求,不但要提交很多的申请材料去证明你的合法性,同时还需要等待他们的审核,最重要的是你还得给他们付昂贵的签名费用。基于上面的考虑,如果不是在公网发布的站点和应用,建议大家在企业内部建立一个自己的 SSL 证书 CA 管理中心,这个 CA 专门用来给企业内网服务器 SSL 证书请求签名、管理生成的证书、撤销已签名的 SSL 证书等。

废话不表,正式进入实战,实战的操作系统是 Windows,安装的 OpenSSL 的版本是 1.1.0g,并把 OpenSSL 的安装目录在操作系统的环境变量里面配置完毕。对于 Linux、Mac 系统,OpenSSL 的命令是类似的,可能文件夹的进入和创建方式不同,请大家自行补脑。

创建文件目录

在创建证书之前,我们需要规划一下 CA 证书中心的文件存放路径,整体的文件结构设计如下:

enter image description here

如果用命令的话,可以使用下面的三条命令:

mkdir c:\rootca   
cd c:\rootca 
mkdir certs crl newcerts private

enter image description here

准备 openSSL.conf 文件

把下面的内容,复制到一个记事本文件里面,然后另为 c:\rootca\openssl.conf:

# 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               = .
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

上面其实定义了一些使用 OpenSSL 的默认参数和配置,比如下面的参数定义了默认 CA 的参数:

[ ca ]
# `man ca`
default_ca = CA_default

而默认 CA_default 其实指向的是下面的配置,其定义了生成的证书存放的路径、序列号、生成的 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 这个配置,其有两个可选值:

(1)policy_strict

其配置详情如下,其主要用来让根 CA 证书来创建中级证书,所以其要求校验匹配的字段就要多点,比如下面其值为 match ,表示 SSL 证书的申请和能签署这些 SSL 证书的 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

(2)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

生成 Root CA 私钥

万事俱备,只欠一试,下面运行一个命令来生成 Root CA 的私钥吧,在命令行(cmd)中输入生成私钥的命令的时候,确保下面的文件夹以及 openssl.conf 已经生成并准备妥当。

enter image description here

在 OpenSSL 的终端,输入下的命令,并输入保护私钥的密码。

genrsa -aes256 -out private/ca.key.pem 4096

如下图所示意:

enter image description here

执行上面的命令后,其就会在 c:\rootca\private 目录下生成一个 ca.key.pem 的私钥文件,如下:

enter image description here

生成 Root CA 证书

输入下面的命令来生成根证书的请求。

req -config openssl.cnf -key private/ca.key.pem -new -x509 -days 7300 -sha256 -extensions v3_ca -out certs/ca.cert.pem

中途输入需要输入保护私钥的密码以及根证书的相关信息,具体窗口如下。

enter image description here

至此,恭喜你已经在 c:\rootca\certs 文件夹下面生成了 Root CA 证书:

enter image description here

查看生成的 Root CA 证书

执行下面的命令来查看确认生成的 Root CA 证书。

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

其主题(Subject)和颁发者(Issuer)是一样,说明其可以作为根证书。

enter image description here

恭喜你,自定义的 CA 认证中心的根证书已经生成完毕。

总结和展望

我们能够直接通过 CA 的根证书来签名新的证书请了,对于一般的自己搭建的企业级 CA 认证中心,有一个根证书应该就足够了,但是对于一个商业上的 CA 认证公司,就远远不够了,因为从安全方面考虑,如果一旦根证书的私钥被泄露,那所有的被签名的证书的信息都能解密了,后果不堪设想并且是灾难性的,所以商业上 CA 认证公司,其往往会把根证书存放在一个物理网络完全隔离的服务器上,其上没有任何外接的设备,包括网络设备、USB 设备等。于此同时,其会用根 CA 证书去签署一些中级 CA 证书作为代理,去签署别的公司或者组织发送过来的 SSL 证书请求。那么,根 CA 证书是如何去签署中级 CA 证书的呢? 敬请期待下一篇的分享。

上一篇
下一篇
目录