Openssl生成并使用自签名CA证书(V3)

最近在搭建局域网环境,涉及到 https 时需要使用自签名证书。走了很多弯路,甚至有人说局域网 IP 没法签发证书。根据我的测试,证书的颁发是自由的,甚至可以一张证书给所有IP签发,但v1证书签发 IP 似乎总是会引发不匹配错误,因此需要签发V3证书。

前期准备

V3 证书的签发需要固定的文件夹结构,这点和 V1 是不一样的。这个文件夹结构可以在/etc/ssl/openssl.cnf中查看。

[ CA_default ]
dir             = ./demoCA              # 生成CA证书的工作目录
certs           = $dir/certs            # 保存生成的 ca 证书
crl_dir         = $dir/crl              # Where the issued crl are kept
database        = $dir/index.txt        # database index file.
new_certs_dir   = $dir/newcerts         # 保存用 CA 签发的其他证书,这里是 pem 格式的备份

certificate     = $dir/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
crl             = $dir/crl.pem          # The current CRL
private_key     = $dir/private/cakey.pem# The private key

也就是说,如果你不手动配置的话,你的 CA 证书目录一定叫demoCA 且 demoCA 包含private & newcerts两个子目录。CA 证书与密钥的文件名只能是cacert.pemcakey.pem

生成目录结构

先新建一个目录,我取名叫 CA 。然后运行

mkdir -p ./demoCA/{private,newcerts} && \
    touch ./demoCA/index.txt && \
    touch ./demoCA/serial && \
    echo 01 > ./demoCA/serial

签发CA证书

创建 CA 配置文件

touch CA.cnf

文件内容

[ req ]
 
default_bits        = 2048
default_keyfile     = r.pem
default_md          = sha256
string_mask         = nombstr
distinguished_name  = req_distinguished_name
req_extensions      = req_ext
x509_extensions     = x509_ext
[ req_distinguished_name ]
 
countryName                 = Country Name (2 letter code)
countryName_default         = CN
stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = BeiJing
localityName                = Locality Name (eg, city)
localityName_default        = BeiJing
organizationName            = Organization Name (eg, company)
organizationName_default    = Hydrogen CA
commonName                  = Common Name (e.g. server FQDN or YOUR name)
commonName_max              = 64
commonName_default          = Hydrogen CA
[ x509_ext ]
 
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid,issuer
basicConstraints       = CA:TRUE
keyUsage               = digitalSignature, keyEncipherment, keyCertSign, cRLSign
[ req_ext ]
 
subjectKeyIdentifier = hash
basicConstraints     = CA:TRUE
keyUsage             = digitalSignature, keyEncipherment, keyCertSign, cRLSign

countryName_default是国家代码
organizationName_default是证书机构的名称
commonName_default是机构的友好名称
其他的可以不改

生成CA证书

生成 CA 证书密钥

openssl genrsa -out ./demoCA/private/cakey.pem 2048

生成 CA 证书

openssl req -new -x509 -key ./demoCA/private/cakey.pem -out ./demoCA/cacert.pem -days 3650 -config CA.cnf

转化为 cer文件(可选)

openssl x509 -inform PEM -in ./demoCA/cacert.pem -outform DER -out ./demoCA/CA.cer

签发服务器证书

服务器证书的文件结构比较自由,命名也随意。我取为 test,下面配置服务器的配置文件。

touch test.cnf

内容如下

[ req ]
 
default_bits        = 2048
default_keyfile     = r.pem
default_md          = sha256
string_mask         = nombstr
distinguished_name  = req_distinguished_name
req_extensions      = req_ext
x509_extensions     = x509_ext
[ req_distinguished_name ]
 
countryName                 = Country Name (2 letter code)
countryName_default         = CN
stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = BeiJing
localityName                = Locality Name (eg, city)
localityName_default        = BeiJing
organizationName            = Organization Name (eg, company)
organizationName_default    = Hydrogen CA
commonName                  = Common Name (e.g. server FQDN or YOUR name)
commonName_max              = 64
commonName_default          = Hydrogen portainer
[ x509_ext ]
 
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid,issuer
basicConstraints       = CA:FALSE
keyUsage               = digitalSignature, keyEncipherment
subjectAltName = @alt_names
[ req_ext ]
 
subjectKeyIdentifier = hash
basicConstraints     = CA:FALSE
keyUsage             = digitalSignature, keyEncipherment
subjectAltName = @alt_names
[ alt_names ]

IP.1    = 10.10.11.10

organizationName_default需要与 CA 的一致。 域名和 IP 在 [alt_names] 中修改,例如

DNS.1   = *.bing.com
DNS.2   = bing.com
IP.1    = 127.0.0.1
IP.2    = 10.10.11.10

生成服务器证书的储存目录

mkdir my

生成服务器密钥

openssl genrsa -out my/test.pem 2048

生成描述文件

openssl req -new -key my/test.pem -out my/test.csr -config test.cnf

签发证书

openssl ca -in my/test.csr -out my/test.crt -days 365 -extensions x509_ext -extfile test.cnf

完成!
文件结构如下

test
├── CA.cnf
├── demoCA
│   ├── CA.cer
│   ├── cacert.pem
│   ├── index.txt
│   ├── index.txt.attr
│   ├── index.txt.old
│   ├── newcerts
│   │   └── 01.pem
│   ├── private
│   │   └── cakey.pem
│   ├── serial
│   └── serial.old
├── my
│   ├── test.crt
│   ├── test.csr
│   └── test.pem
└── test.cnf

参考&引用

[1].https://2heng.xin/2018/12/16/your-own-ca-with-openssl/
这文章写的太好了,我只是略作改动
[2].https://docs.microsoft.com/zh-cn/azure/application-gateway/self-signed-certificates
生成 V1 的证书看微软的文档就够了

updatedupdated2025-03-232025-03-23