如您需要技术咨询、解决方案定制、故障排除、运维监控等服务,可联系ericwcn#at#163.com。

OpenSSL 创建私有的PKI CA数字证书认证中心

Linux 立杰 216℃

1.简介

OpenSSL是一款开源的用于加密和认证的类库.她提供一些命令行工具,用于签发基于RSA非对称密码技术的数字证书.有时可以用她来充当简单的PKC/CA证书办法机构
CA即受信任的认证中心,由她维护一定范围内的信任体系.在该信任体系中的所有用户、服务器,都被发放一张数字证书来证明其身份已经被鉴定过,并为其发放一张数字证书,每次在进行数据通信的时候,通过互相检查对方的数字证书即可判别是否是本信任域中的可信体。
很多互联网站数据证书来加密客户端与服务器端之间的数据通信,保障数据在网络中的传输安全.这就需要拥有全球访问受信任的CA机构来为这些实体签发证书,来表明其身份.(如:VeriSign/DigiCert).
有些时候,我们需要构建一套用于公司内部应用程序(Apache/Nginx/OpenVPN…)使用的数字证书,用于保证内部服务器或与外网服务器之间的数据传输安全.这时我们就需要构建一套自己的PKI/CA数字证书信任体系.
openssl-3

2.创建CA根证书

CA根证书是PKI体系中重要的组成部分,要建立树状的受信任体系,首先CA自身需要表明身份,并建立树根,其他的中级证书都依赖该根来签发证书,并通过根证书建立彼此的信任关系.CA证书由私钥Root Key和公钥Root Cert Pem组成。
CA根证书并不直接颁发服务器证书和客户端证书,仅用来颁发一个或多个中级证书,中级证书代理Root CA向用户和服务器颁发证书。同时,为了保证Root CA的安全,应保证Root Key处于离线并安全保存。
创建Root CA目录
选择一个目录用于存储所有的私钥和证书公钥。(/root/ca)

$ mkdir /root/ca

创建目录结构,生成index.txt和serial文件,用于作为文件数据库追踪以前发的证书。

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

备注:
certs:存放已签发的证书,newcerts:存放CA生成的新证书,private:存放私钥,crl:存放以吊销的证书,index.txt:OpenSSL定义的已签发证书的文本数据库文件,通常该文件在初始化时为空。
serial:签发证书时使用的序列号参考文件,该文件中的序列号为16进制数,初始化时必须提供并包含一个有效的序列号。

创建OpenSSL配置文件 Root CA

为openssl 创建Root CA配置文件,保存在/root/ca/openssl.cnf
文件中[ ca ]的部分是必须存在的,用于告诉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

创建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

为中级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>.
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           =

在OpenSSL中,出来基本的必要信息外,还有一些可扩展的选项可用于证书签发。

[ 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证书签发的扩展选项,其中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

在[ user_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 ]中,定义了签发服务器证书时的证书签发策略。

[ 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

在 [ crt_ext ]用于定义创建证书吊销列表时的策略。

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

定义在线证书使用策略ocsp

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

创建Root CA Key

生成的root key必须保证其绝对的安全,并使用aes-256加密和高强度密码保护。

$ 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

备注:
genrsa:使用RSA算法产生私钥;-aes256:使用256位密钥的AES算法对私钥进行加密;-out:输出文件目录;4096:指定密钥的长度。

创建Root CA证书

使用Root Key(ca.key.pem)创建Root CA证书(ca.cert.pem).需要为Root CA指定较长的有效期,如20年。一旦Root CA证书过期,其所有签发的证书将都不可用。
在使用req命令时,必须使用-config 指定配置文件,否则程序默认使用/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

 

验证签发的Root CA证书

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

确认Signature Algorithm使用的签名算法
确认Validity中的证书有效期
确认Public-Key长度
确认Issuer,签发者信息
确认Subject,Root CA证书为自签名证书,与Issuer信息相同
我们启用x509 v3扩展信息,在输出的文件中,还将包括一些扩展的信息,如:X509v3 Subject Key Identifier/X509v3 Authority Key Identifier/X509v3 Basic Constraints等。

创建中级CA证书密钥对

中级CA证书用于代替Root CA签发客户端证书和服务器证书,根证书负责签发中级CA证书并维护受信任的证书链.
使用中级证书主要是处于安全考虑,因为Root CA Key始终处理物理隔离并能够保障私钥的绝对安全,在中级CA证书的私钥发生泄漏后,可以通过Root CA吊销该证书,并重新签发新的中级证书密钥对.

创建中级CA证书目录结构
与Root CA类是,我们需要为中级CA证书创建用于存储证书的目录.我们将中级证书所有内容保存在/root/ca/intermediate目录下面,并创建类是Root CA的目录结构.

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

在中级CA证书目录下,新建名为crlnumber的文本文件,用于保存证书吊销列表.

$ echo 1000 > /root/ca/intermediate/crlnumber

创建中级CA证书OpenSSL配置文件
将中级CA证书的配置文件保存在/root/ca/intermediate/openssl.cnf,相比Root 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

完整的配置文件内容如下:

# 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

生成中级CA证书私钥

创建中级证书私钥,使用AES-256加密.

$ cd /root/ca
$ openssl genrsa -aes256 -out intermediate/private/intermediate.key.pem 4096
$ chmod 400 intermediate/private/intermediate.key.pem

生成中级CA证书请求

使用intermediate.key.pem为生成中级CA证书,同时使用Root CA对证书进行签名.Common Name不能重复.
如果使用中级CA签发服务器证书和客户端证书,需要指定配置文件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

生成中级CA证书

使用Root CA签发中级CA证书,并为其指定v3_intermediate_ca扩展属性签发证书.中级证书的有效期要短于根证书.
确认使用Root CA的openssl.cnf签发中级证书

$ cd /root/ca
$ openssl ca -config openssl.cnf -extenstions v3_intermediate_ca -days 3650 -notext -md sha256 -in intermediate/csr/intermediate.csr.pem -out intermediate/certs/intermediate.cert.pem
$ chmod 444 intermediate/certs/intermediate.cert.pem

注意:index.txt是openssl的文件数据库,不要直接修改或删除该文件.

验证中级CA证书内容

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

使用Root CA根证书验证中级证书的证书链信任关系,OK表示证书链受信任.

$ openssl verify -CAfile certs/ca.cert.pem  intermediate/certs/intermediate.cert.pem
intermediate.cert.pem: OK

创建证书链文件

当应用程序(Web浏览器)尝试验证签发的证书有效性时,会尝试验证中级CA证书和上级根证书.
在证书链文件中,必须同时包含根证书和中级证书.因为客户端不知知道签发的这张私有的CA根证书,你可以在所有需要访问的客户端将Root 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证书为服务器签发证书,用来加密服务器与客户端之间的数据通信.如果您在服务器使用OpenSSL已经创建过了csr证书请求,则可跳过生成Server Key的过程.

创建服务器证书私钥

我们在创建Root CA和intermediate CA使用了4096bit密码加密,服务器和客户端证书一般有效期为几年,可以使用2048bit加密.
虽然4096bit密码要更安全,但在服务器进行TLS握手和数字签名验证时会降低访问速度,因此一般Web服务器还是建议使用2048Bit密码加密.
如果您在创建私钥时设置了密码,则每次服务重启时都需要提供这一密码,因此不建议为服务器证书设置密码保护,可以使用aes256密码算法进行加密.

$ cd /root/ca
$ openssl genrsa -aes256 -out intermediate/private/r.wanglijie.cn.key.pem 2048
$ chmod 400 intermediate/private/r.wanglijie.cn.key.pem

创建服务器证书请求csr

使用创建的服务器私钥生成签发证书请求csr文件.csr文件无需指定中级CA证书机构.但是必须指定Common Name,一般为域名或IP地址.

$ cd /root/ca
$ openssl req -config intermediate/openssl.cnf -new -sha256 -days 365 -key intermediate/private/r.wanglijie.cn.key.pem -out intermediate/csr/r.wanglijie.cn.csr.pem

从证书请求csr创建服务器证书

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

注意:
在签发证书时,-extensions 选项用于指定要签发的证书类型。服务器证书使用“server_cert ”,客户端证书使用“usr_cert”
证书签发完毕后,将会在intermediate/index.txt文件中新增一条记录。

查看签发的证书

$ openssl x509 -noout -text  -in intermediate/certs/r.wanglijie.cn.cert.pem

使用CA证书链(ca-chain.cert.pem)验证签发证书的信任关系

$ openssl verify -CAfile intermediate/certs/ca-chain.cert.pem intermediate/certs/r.wanglijie.cn.cert.pem

部署证书

在证书签发完毕后,可以将证书部署在Nginx,Apahce或其他的应用服务器上。如果您需要将证书部署在IIS或Tomcat中,请查看下文openssl证书格式转换。

常用数字证书格式相互转换-OpenSSL/Keytool/Jks2pfx

访问英文原文

转载请注明:知识库 » OpenSSL 创建私有的PKI CA数字证书认证中心

喜欢 (0)