使用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再签发网站证书。
证书生成
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