OpenSSL与根和中间CA创建证书链

时间:2020-02-23 14:40:10  来源:igfitidea点击:

Openssl创建证书链需要根CA和中间证书,在本文中,我将共享分步指南,以创建根证书和中间证书,然后使用这些证书在Linux中创建证书CA捆绑包。
我希望我们对与OpenSSL一起使用的所有术语有所了解。

根vs中级证书

  • 证书链或者证书CA捆绑包是一系列证书,其中链中的每个证书都由后续证书签名。

  • 根CA是证书链的顶层,而中间CA或者子CA是从中间根发出的证书颁发机构。

  • 通常,根CA不会直接签署服务器或者客户端证书。

  • 根CA仅用于创建一个或者多个中间CA,这些CA被根CA信任以代表它们签名证书。
    这是最佳做法。

  • 由于根密钥的任何破坏都是灾难性的,它允许根密钥保持脱机状态并尽可能地不使用。

  • 中间证书颁发机构(CA)是可以代表根CA签署证书的实体。

  • 根CA签署中间证书,形成信任链。

  • 使用中间CA的目的主要是为了安全性。

  • 根密钥可以保持脱机状态,并尽可能少地使用。

  • 如果中间密钥被泄露,则根CA可以撤销中间证书并创建新的中间密码对。

安装OpenSSL

在RHEL/CentOS 7/8上,我们可以分别使用yum或者dnf;而在Ubuntu上,可以使用" apt-get"安装openssl rpm。

说明:

在RHEL系统上,我们必须具有RHN的有效订阅,或者我们可以配置本地脱机存储库,通过该本地脱机存储库,yum软件包管理器可以安装提供的rpm及其依赖项。

[root@centos8-1 ~]# yum -y install openssl

使用加密密码的OpenSSL加密数据

当我们为根CA证书创建私钥时,我们可以选择对私钥使用加密,也可以创建不进行任何加密的密钥。
就像我们选择使用3DES,AES这样的加密方式创建私钥一样,每次尝试访问私钥时,我们都必须提供密码。

之前我们介绍过使用盐腌密码对openssl encd数据进行加密的步骤。

因此,将不再其中重复这些步骤。

对于本文中的所有示例,我们将使用相同的加密密码文件,以演示openssl创建证书链示例。

创建OpenSSL根CA目录结构

我们还可以使用所有证书创建CA捆绑包,而无需创建任何目录结构和使用一些手动调整,但是让我们按照漫长的过程来更好地理解。

在RHEL/CentOS 7/8中,所有证书的默认位置都在/etc/pki/tls下。
但是对于本文,我们将创建一个新的目录结构"/root/tls /"来存储我们的证书。

创建一个父目录来存储证书

[root@centos8-1 ~]# mkdir /root/tls
[root@centos8-1 ~]# cd /root/tls

在CA的根目录中,我们需要创建两个子目录:

certs:这将用于保留我们通过CA颁发的所有证书的副本。
private:这将用于保留CA证书的私钥的副本。

重要的提示:

CA所使用的大多数文件对系统上的任何人或者至少使用我们CA所颁发的证书的任何人都是可见的。
一个值得注意的例外是CA证书的私钥。
切勿将私钥透露给未经授权从我们的CA颁发证书或者CRL的任何人。
私钥应该存储在硬件中,或者至少存储在永远不会放在网络上的计算机上

[root@centos8-1 tls]# mkdir certs private

除了密钥生成之外,我们还将创建CA基础结构所需的三个文件。

一个"序列"文件用于"跟踪用于颁发证书的最后一个序列号"。
重要的是,永远不会从同一CA颁发具有相同序列号的两个证书。
OpenSSL如何处理此文件有些古怪。
它期望该值以十六进制表示,并且必须至少包含两位数,因此我们必须在其前面加上一个零以填充该值。

[root@centos8-1 tls]# echo 01 > serial

接下来,我们将创建" index.txt"文件,该文件是一种"数据库",用于跟踪CA颁发的证书。
由于此时尚未颁发证书,并且OpenSSL要求该文件存在,因此我们将简单地创建一个空文件。

[root@centos8-1 tls]# touch index.txt

检查/root/tls下的内容列表

[root@centos8-1 tls]# ls -l
total 32
drwxr-xr-x 2 root root 4096 Apr  8 22:29 certs
-rw-r--r-- 1 root root    0 Apr  9 03:36 index.txt
-rw-r--r-- 1 root root   32 Apr  8 23:25 mypass.enc
drwxr-xr-x 2 root root 4096 Apr  9 03:34 private
-rw-r--r-- 1 root root    3 Apr  9 03:37 serial

第4步:为根CA证书配置openssl.cnf

在RHEL/CentOS 7/8中的/etc/pki/tls/openssl.cnf下,我们将有一个默认配置文件" openssl.cnf",由openssl rpm添加。
我们会将文件复制到自定义证书位置,即"/root/tls",并将修改该文件的内容以创建根CA证书

HOME                    = .
RANDFILE                = $ENV::HOME/.rnd
oid_section             = new_oids
openssl_conf = default_modules
[ default_modules ]
ssl_conf = ssl_module
[ ssl_module ]
system_default = crypto_policy
[ crypto_policy ]
.include /etc/crypto-policies/back-ends/opensslcnf.config
[ new_oids ]

用于CA函数的OpenSSL命令恰当地命名为ca,因此我们感兴趣的第一部分称为ca
就我们的目的而言,本节非常简单,只包含一个键:default_ca。
该值是包含默认CA配置的部分的名称。
" [CA_default]"部分包含一系列默认值。
确保声明我们先前选择的目录/root/tls。

x509_extensions键指定一个部分的名称,该部分将包含要添加到我们的CA颁发的每个证书中的扩展名。

[ ca ]
default_ca      = CA_default            # The default ca section
[ CA_default ]
dir             = /root/tls             # Where everything is kept
certs           = $dir/certs            # Where the issued certs are kept
database        = $dir/index.txt        # database index file.
                                        # several certs with same subject.
new_certs_dir   = $dir/certs            # default place for new certs.
certificate     = $dir/certs/cacert.pem       # The CA certificate
serial          = $dir/serial           # The current serial number
crlnumber       = $dir/crlnumber        # the current crl number
                                        # must be commented out to leave a V1 CRL
private_key     = $dir/private/cakey.pem # The private key
name_opt        = ca_default            # Subject Name options
cert_opt        = ca_default            # Certificate field options
default_days    = 365                   # how long to certify for
default_crl_days= 30                    # how long before next CRL
default_md      = sha256                # use SHA-256 by default
preserve        = no                    # keep passed DN ordering
policy          = policy_match

policy键指定将用于默认策略的部分的名称。
策略定义是一组与证书可分辨名称中的字段同名的密钥。
对于每个键或者字段,都有三个合法值:"匹配","提供"或者"可选"。

  • " match:"表示证书请求中具有该名称的字段必须与CA证书中的相同字段匹配。

  • supplied:表示证书请求必须包含该字段。

  • optional:表示证书请求中不需要该字段。

我们将应用policy_match来创建根CA证书,因此我们将其添加为CA_default下的policy的默认值。

[ policy_match ]
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

policy_anything用于创建中间CA证书

[ policy_anything ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

创建证书签名请求(CSR)或者证书时,将应用req部分下的值。
x509_extensions键指定包含我们要包含在证书中的扩展名的部分的名称。

[ req ]
default_bits            = 4096
default_md              = sha256
default_keyfile         = privkey.pem
distinguished_name      = req_distinguished_name
x509_extensions         = v3_ca
string_mask             = nombstr

" eq_distinguished_name"密钥确定OpenSSL如何获取填写证书的专有名称所需的信息。
我提供的默认值很少,而必须提供公共名称,如我们在policy键下定义的一样。

[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
countryName_default             = IN
countryName_min                 = 2
countryName_max                 = 2
stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = Some-State
localityName                    = Locality Name (eg, city)
localityName_default            = BANGALORE
0.organizationName              = Organization Name (eg, company)
0.organizationName_default      = theitroad
organizationalUnitName          = Organizational Unit Name (eg, section)
commonName                      = Common Name (eg, your name or your server\'s hostname)
commonName_max                  = 64
emailAddress                    = Email Address
emailAddress_max                = 64

这些是我们将与openssl创建证书链一起使用的扩展。
我们将使用v3_ca扩展名来创建根CA证书,并使用v3_intermediate扩展名来中级CA证书。

[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = critical,CA:true
[ v3_intermediate_ca ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

生成根CA私钥

  • 我们将使用4096位和3DES加密创建根CA密钥

  • 我正在使用加密的密码文件来提供私钥的密码

  • 我们将这个私钥存储在/root/tls/private下。

[root@centos8-1 tls]# openssl genrsa -des3 -passout file:mypass.enc -out private/cakey.pem 4096
Generating RSA private key, 4096 bit long modulus (2 primes)
.......................................................................++++
.......................++++
e is 65537 (0x010001)

重要的提示:

如果此密钥被盗用,则CA的完整性将受到损害,这实质上意味着,无论颁发的证书是在密钥被盗用之前还是之后,都将不再受信任。

OpenSSL验证根CA密钥

我们将使用openssl命令查看私钥的内容:

[root@centos8-1 tls]# openssl rsa -noout -text -in private/cakey.pem -passin file:mypass.enc
RSA Private-Key: (4096 bit, 2 primes)
<Output trimmed>

创建自己的根CA证书

  • OpenSSL创建证书链需要根证书和中间证书。
    在此步骤中,我们将替换VeriSign,Thawte等。

  • 使用根CA密钥cakey.pem创建根CA证书cacert.pem

  • 给予根证书有效期较长。
    一旦根证书过期,则由CA签名的所有证书都将失效。

  • 每当使用" openssl req"工具时,都必须指定要与" -config"方法一起使用的配置文件,否则OpenSSL将默认为" /etc/pki/tls/openssl.cnf"

  • 我们将使用v3_ca扩展名来创建CA证书

重要的提示:

" CA和服务器证书的通用名称(CN)不能匹配",否则将发生命名冲突,稍后我们将收到错误消息。

使用以下命令创建根证书颁发机构证书cacert.pem

[root@centos8-1 tls]# openssl req -new -x509 -days 3650 -passin file:mypass.enc -config openssl.cnf -extensions v3_ca -key private/cakey.pem -out certs/cacert.pem
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
----
Country Name (2 letter code) [IN]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) [BANGALORE]:
Organization Name (eg, company) [theitroad]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:centos8-1
Email Address []:[email protected]

将证书的格式更改为PEM格式

[root@centos8-1 tls]# openssl x509 -in certs/cacert.pem -out certs/cacert.pem -outform PEM

OpenSSL验证证书

对openssl执行以下命令以验证根CA证书

[root@centos8-1 tls]# openssl x509 -noout -text -in certs/cacert.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            55:b2:c2:5e:7b:95:4a:05:78:32:82:6f:b1:60:a0:92:03:96:0b:30
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = IN, ST = Some-State, L = BANGALORE, O = theitroad, CN = centos8-1, emailAddress = [email protected]
        Validity
            Not Before: Apr 11 11:34:22 2017 GMT
            Not After : Apr  9 11:34:22 2030 GMT
        Subject: C = IN, ST = Some-State, L = BANGALORE, O = theitroad, CN = centos8-1, emailAddress = [email protected]
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (4096 bit)
<Output trimmed>

输出显示:

  • 使用的"签名算法"

  • 证书有效期的"日期"

  • "公钥"位的长度

  • "签发者",即签署证书的实体

  • "主题",指的是证书本身

说明:

由于证书是自签名的,因此颁发者和主题是相同的。

输出还显示X509v3扩展。
我们应用了v3_ca扩展名,因此[[v3_ca]`中的选项应反映在输出中。

X509v3 extensions:
            X509v3 Subject Key Identifier:
                0B:FE:44:49:A9:90:96:9A:19:17:56:55:2D:70:B0:0D:D8:5D:9A:73
            X509v3 Authority Key Identifier:
                keyid:0B:FE:44:49:A9:90:96:9A:19:17:56:55:2D:70:B0:0D:D8:5D:9A:73
            X509v3 Basic Constraints: critical
                CA:TRUE

创建OpenSSL中级CA目录结构

现在,要完成openssl create证书链的设置,我们还将需要CA捆绑包的中间证书。
我们将在父文件夹"/root/tls"下创建新的目录结构"/root/tls/intermediate",以将两个证书文件分开。

[root@centos8-1 tls]# mkdir /root/tls/intermediate
[root@centos8-1 tls]# cd /root/tls/intermediate

我们还将在/root/tls/intermediate下创建子目录,以存储我们的密钥和证书文件。
我们还需要为根CA证书创建的" serial"和" index.txt"文件。

[root@centos8-1 intermediate]# mkdir certs csr private
[root@centos8-1 intermediate]# touch index.txt
[root@centos8-1 intermediate]# echo 01 > serial

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

[root@centos8-1 intermediate]# echo 01 > /root/tls/intermediate/crlnumber

为中级CA证书配置openssl.cnf

将用于我们的根CA证书的" openssl.cnf"从" /root/tls/openssl.cnf"复制到" /root/tls/intermediate/openssl.cnf"。
与根CA证书配置文件相比,以下是我们已更改的选项:

dir             = /root/tls/intermediate               # Where everything is kept
certificate     = $dir/certs/intermediate.cacert.pem   # The CA certificate
private_key     = $dir/private/intermediate.cakey.pem  # The private key
policy          = policy_anything

步骤9:生成中间CA密钥

使用具有3DES加密的openssl genrsa和我们的加密密码短语文件生成中间CA密钥" ca-intermediate.key",以避免出现任何密码提示。

[root@centos8-1 tls]# openssl genrsa -des3 -passout file:mypass.enc -out intermediate/private/intermediate.cakey.pem 4096
Generating RSA private key, 4096 bit long modulus (2 primes)
...........................................................................++++
............................................................................++++
e is 65537 (0x010001)

0:创建立即CA证书签名请求(CSR)

  • 使用中间CA密钥创建证书签名请求(CSR)。

  • 详细信息通常应与根CA相匹配。

  • "但是,通用名称必须不同。
    "

接下来,我们将在/root/tls/intermediate/csr下创建中间CA证书签名请求(CSR),其到期值小于根CA证书

[root@centos8-1 tls]# openssl req -new -sha256 -config intermediate/openssl.cnf -passin file:mypass.enc  -key intermediate/private/intermediate.cakey.pem -out intermediate/csr/intermediate.csr.pem
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
----
Country Name (2 letter code) [IN]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) [BANGALORE]:
Organization Name (eg, company) [theitroad]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:centos8-1 Intermediate CA
Email Address []:[email protected]
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

1:签名并生成立即CA证书

现在,在结束openssl创建证书链之前的最后一步,我们需要使用在上一步中创建的证书签名请求创建立即CA证书。
我们将使用/root/tls/openssl.cnf中的v3_intermediate_ca扩展名在/root/tls/intermediate/certs/intermediate.cacert.pem下创建中间CA证书。

[root@centos8-1 tls]# openssl ca -config openssl.cnf -extensions v3_intermediate_ca -days 2650 -notext -batch -passin file:mypass.enc -in intermediate/csr/intermediate.csr.pem -out intermediate/certs/intermediate.cacert.pem
Using configuration from openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1)
        Validity
            Not Before: Apr  9 13:40:23 2017 GMT
            Not After : May 12 13:40:23 2027 GMT
        Subject:
            countryName               = IN
            stateOrProvinceName       = Some-State
            organizationName          = theitroad
            commonName                = centos8-1 Intermediate CA
            emailAddress              = [email protected]
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                A4:07:28:66:F1:71:CD:0B:62:2E:01:8C:6B:04:5B:CC:D0:96:24:89
            X509v3 Authority Key Identifier:
                keyid:0B:FE:44:49:A9:90:96:9A:19:17:56:55:2D:70:B0:0D:D8:5D:9A:73
            X509v3 Basic Constraints: critical
                CA:TRUE, pathlen:0
            X509v3 Key Usage: critical
                Digital Signature, Certificate Sign, CRL Sign
Certificate is to be certified until May 12 13:40:23 2027 GMT (2650 days)
Write out database with 1 new entries
Data Base Updated

" index.txt"文件是OpenSSL ca工具存储证书数据库的位置。
请勿手动删除或者编辑此文件。
"它现在应该包含引用中间证书的行。
"

[root@centos8-1 tls]# cat index.txt
V       270712134023Z           01      unknown /C=IN/ST=Some-State/O=theitroad/CN=centos8-1 Intermediate CA/[email protected]

OpenSSL验证证书

验证中间CA证书内容

[root@centos8-1 tls]# openssl x509 -noout -text -in intermediate/certs/intermediate.cacert.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1 (0x1)
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = IN, ST = Some-State, L = BANGALORE, O = theitroad, CN = centos8-1, emailAddress = [email protected]
        Validity
            Not Before: Apr  9 13:40:23 2017 GMT
            Not After : May 12 13:40:23 2027 GMT
        Subject: C = IN, ST = Some-State, O = theitroad, CN = centos8-1 Intermediate CA, emailAddress = [email protected]
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (4096 bit)

接下来,openssl根据根证书验证中间证书。
OK(确定)表示信任链完整无缺。

[root@centos8-1 tls]# openssl verify -CAfile certs/cacert.pem intermediate/certs/intermediate.cacert.pem
intermediate/certs/intermediate.cacert.pem: OK

将证书的格式转换为PEM格式

[root@centos8-1 tls]# openssl x509 -in intermediate/certs/intermediate.cacert.pem -out intermediate/certs/intermediate.cacert.pem -outform PEM

2:OpenSSL创建证书链(证书捆绑包)

要打开openssl创建证书链(证书捆绑包),请将中间证书和根证书连接在一起。

在下面的示例中,我将Linux中的根CA证书和中级CA证书组合到openssl创建证书链中。
我们稍后将使用此文件来验证由中间CA签名的证书。

[root@centos8-1 tls]# cat intermediate/certs/intermediate.cacert.pem certs/cacert.pem > intermediate/certs/ca-chain-bundle.cert.pem

OpenSSL验证证书链

openssl创建证书链后,使用以下命令来验证证书链:

[root@centos8-1 tls]# openssl verify -CAfile certs/cacert.pem intermediate/certs/ca-chain-bundle.cert.pem 
intermediate/certs/ca-chain-bundle.cert.pem: OK

要验证在线页面(例如Google)的证书链,请执行以下操作:

[root@centos8-1 certs]# openssl s_client -quiet -connect google.com:443
depth=2 OU = GlobalSign Root CA - R2, O = GlobalSign, CN = GlobalSign
verify return:1
depth=1 C = US, O = Google Trust Services, CN = GTS CA 1O1
verify return:1
depth=0 C = US, ST = California, L = Mountain View, O = Google LLC, CN = *.google.com
verify return:1

要显示来自Google证书链的证书,请执行以下操作:

[root@centos8-1 certs]# openssl s_client -showcerts -connect google.com:443
CONNECTED(00000003)
depth=2 OU = GlobalSign Root CA - R2, O = GlobalSign, CN = GlobalSign
verify return:1
depth=1 C = US, O = Google Trust Services, CN = GTS CA 1O1
verify return:1
depth=0 C = US, ST = California, L = Mountain View, O = Google LLC, CN = *.google.com
verify return:1
<Output trimmed>