lamess / 使用OpenSSL生成可信任的证书

Created Thu, 13 Jun 2024 11:27:54 +0800 Modified Tue, 04 Mar 2025 17:23:18 +0800

使用OpenSSL生成三级可信证书

Forked from 局域网内搭建浏览器可信任的SSL证书and 多级证书颁发CA服务器部署 and 使用 OpenSSL 构建 X.509 三级证书体系


原理

X.509

ITU 最早在 1993 年就指定了X.509数字证书标准,它其实是作为X.500项目的一部分,X.500项目的作用是定义了唯一标识一个实体的方法,该实体可以是机构、组织、个人或一台服务器。而X.509则把该实体与公钥所绑定关联起来,从而提供了通信实体的鉴别机制,也就是目前最流行的X.509数字证书。

X.509体系下,实际上网站使用的证书都不是由根CA直接签发的。一般是由根CA签发中级CA,由中级CA再签发网站证书。

R O O T C A I I I n n n t t t e e e r r r m m m e e e d d d i i i a a a C C C A A A 1 2 3 S S S S e e e e r r r r v v v v e e e e r r r r C C C C A A A A 1 2 3 x

证书生成

OpenSSL相关

直接使用OpenSSL创建根CA证书以及相关的公钥。而在OpenSSL的部分配置是无法直接在命令行中指定的,因此需要准备一份配置文件进行相关配置。
OpenSSL源码中提供了标准配置文件,以此为模板生成一份配置即可。

这里需要输入机构信息,参数含义如下:

参数
Country Name 国家代码,比如中国就是CN
State or Province Name 省名称
Locality Name 城市名称
Organization Name 机构名称
Organizational Unit Name 机构单位名称
Common Name 重点参数:授权的单位名称
Email Address 邮件地址

根CA证书

开始操作,首先建立目录,并生成一份配置文件。

mkdir -p /opt/ca/root
mkdir /opt/ca/root/key
mkdir /opt/ca/root/newcerts
touch /opt/ca/root/index.txt
touch /opt/ca/root/index.txt.attr
echo 01 > /opt/ca/root/serial
cat > /opt/ca/root/openssl.cnf <<EOF
[ ca ]
default_ca    = CA_default
[ CA_default ]
dir                     = /opt/ca/root
certs                   = \$dir/certs
crl_dir                 = \$dir/crl
database                = \$dir/index.txt
new_certs_dir           = \$dir/newcerts
certificate             = \$dir/key/cacert.crt
serial                  = \$dir/serial
crlnumber               = \$dir/crlnumber
crl                     = \$dir/crl.pem
private_key             = \$dir/key/cakey.pem
RANDFILE                = \$dir/key/.rand
unique_subject          = no
x509_extensions         = usr_cert
copy_extensions         = copy
name_opt                = ca_default
cert_opt                = ca_default
default_days            = 36500
default_crl_days        = 30
default_md              = sha256
preserve                = no
policy                  = policy_ca
[ policy_ca ]
countryName             = supplied
stateOrProvinceName     = supplied
organizationName        = supplied
organizationalUnitName  = supplied
commonName              = supplied
emailAddress            = optional
[ req ]
default_bits            = 8192
default_keyfile         = privkey.pem
distinguished_name      = req_distinguished_name
attributes              = req_attributes
x509_extensions         = v3_ca
string_mask             = utf8only
utf8                    = yes
prompt                  = no
[ req_distinguished_name ]
countryName             = CN
stateOrProvinceName     = Province Name
localityName            = city
organizationName        = company
organizationalUnitName  = section
commonName              = Root CA
[ usr_cert ]
basicConstraints = CA:TRUE
[ v3_ca ]
basicConstraints = CA:TRUE
[ req_attributes ]
EOF

创建私钥。

openssl genrsa -out /opt/ca/root/key/cakey.pem 8192

创建CA证书请求文件。

openssl req -new -key /opt/ca/root/key/cakey.pem -out /opt/ca/root/key/ca.csr -config /opt/ca/root/openssl.cnf

将根CA证书进行自签。

yes y | openssl ca -selfsign -in /opt/ca/root/key/ca.csr -out /opt/ca/root/key/cacert.crt -config /opt/ca/root/openssl.cnf

这样就生成了根CA的相关证书和私钥,可以用于签发中级CA。

中级CA证书

同样地,建立中级CA的目录,并生成一份配置文件。

mkdir /opt/ca/intermediate
mkdir /opt/ca/intermediate/key
mkdir /opt/ca/intermediate/newcerts
touch /opt/ca/intermediate/index.txt
touch /opt/ca/intermediate/index.txt.attr
echo 01 > /opt/ca/intermediate/serial
cat > /opt/ca/intermediate/openssl.cnf << EOF
[ ca ]
default_ca    = CA_default
[ CA_default ]
dir                     = /opt/ca/intermediate
certs                   = \$dir/certs
crl_dir                 = \$dir/crl
database                = \$dir/index.txt
new_certs_dir           = \$dir/newcerts
certificate             = \$dir/key/cacert.crt
serial                  = \$dir/serial
crlnumber               = \$dir/crlnumber
crl                     = \$dir/crl.pem
private_key             = \$dir/key/cakey.pem
RANDFILE                = \$dir/key/.rand
unique_subject          = no
x509_extensions         = usr_cert
copy_extensions         = copy
name_opt                = ca_default
cert_opt                = ca_default
default_days            = 36500
default_crl_days        = 30
default_md              = sha256
preserve                = no
policy                  = policy_ca
[ policy_ca ]
countryName             = supplied
stateOrProvinceName     = supplied
organizationName        = supplied
organizationalUnitName  = supplied
commonName              = supplied
emailAddress            = optional
[ req ]
default_bits            = 8192
default_keyfile         = privkey.pem
distinguished_name      = req_distinguished_name
attributes              = req_attributes
x509_extensions         = v3_ca
string_mask             = utf8only
utf8 = yes
prompt = no
[ req_distinguished_name ]
countryName             = CN
stateOrProvinceName     = Province Name
localityName            = city
organizationName        = company
organizationalUnitName  = section
commonName              = Intermediate CA
[ usr_cert ]
basicConstraints        = CA:FALSE
[ v3_ca ]
basicConstraints        = CA:TRUE
[ req_attributes ]
EOF

创建私钥。

openssl genrsa -out /opt/ca/intermediate/key/cakey.pem 8192

创建中级CA证书请求文件。

openssl req -new -key /opt/ca/intermediate/key/cakey.pem -out /opt/ca/intermediate/key/ca.csr -config /opt/ca/intermediate/openssl.cnf

用根CA证书签发中级CA证书。

yes y | openssl ca -in /opt/ca/intermediate/key/ca.csr -out /opt/ca/intermediate/key/cacert.crt -config /opt/ca/root/openssl.cnf

这样就生成了中级CA,用于签发服务器证书。

服务器证书

接下来建立服务器证书的目录,并生成一份配置文件。

mkdir -p /opt/ca/server
cat > /opt/ca/server/openssl.cnf <<EOF
[ req ]
prompt                  = no
distinguished_name      = server_distinguished_name
req_extensions          = req_ext
x509_extensions         = v3_req
attributes              = req_attributes
[ server_distinguished_name ]
countryName             = CN
stateOrProvinceName     = Province Name
localityName            = city
organizationName        = company
organizationalUnitName  = section
commonName              = Common Name (e.g. server FQDN or YOUR name)
[ v3_req ]
basicConstraints        = CA:FALSE
keyUsage                = nonRepudiation, digitalSignature, keyEncipherment
[ req_attributes ]
[ req_ext ]
subjectAltName          = @alternate_names
[ alternate_names ]
DNS.1                   = example.com
DNS.2                   = *.example.com
IP.1                    = 192.168.1.1
IP.2                    = 192.168.1.2
EOF

在服务器证书的commonName中应该使用服务器的FQDN。
注意alternate_names参数是重点,需要将里面配置为最终服务端需要的域名或者IP。
这里可以写多个,支持通配符。可以自行添加DNS.X = XXXXXX和IP.x=xxx.xxx.xxx.xxx。

创建私钥。

openssl genrsa -out /opt/ca/server/privkey.pem 8192

创建服务器证书请求文件。

openssl req -new -key /opt/ca/server/privkey.pem -out /opt/ca/server/server.csr -config /opt/ca/server/openssl.cnf

用中级CA证书签发服务器证书。

yes y | openssl ca -in /opt/ca/server/server.csr -out /opt/ca/server/certificate.crt -config /opt/ca/intermediate/openssl.cnf

最后聚合证书,生成证书链。

cat /opt/ca/intermediate/key/cacert.crt /opt/ca/root/key/cacert.crt | tee /opt/ca/server/chain.crt
cat /opt/ca/server/certificate.crt /opt/ca/intermediate/key/cacert.crt /opt/ca/root/key/cacert.crt | tee /opt/ca/server/fullchain.crt

证书使用

Nginx配置

在SSL的配置中指定证书路径即可。

server {
    listen       443 ssl;
    ssl_certificate      /opt/ca/server/fullchain.crt;
    ssl_certificate_key  /opt/ca/server/privkey.pem;
    location / {
        root   html;
        index  index.html index.htm;
    }
}

重启nginx生效。

Windows安装证书

将根CA证书安装到“受信任的根证书颁发机构”即可。

使用pkcs12文件

对于需要同时存储和传输证书和私钥的场景,可以将私钥文件和证书聚合为.pfx文件,导入到支持PKCS#12格式的应用程序中。

openssl pkcs12 -export -inkey /opt/ca/server/privkey.pem -in /opt/ca/server/fullchain.crt -out /opt/ca/server/certificate.pfx