摘要: 生成自签名证书的操作可以整合到一条命令中,也可以拆分为生成私钥+生成公钥两步进行。生成出的证书既可以直接作为SSL证书使用,也可以当作CA证书,签发子证书作为SSL证书使用。

生成自签名证书

网上的教程中,常见的生成自签名证书的方法有两种:

方法一

将生成公钥和私钥的过程整合到一行命令中:

1
2
3
4
5
6
7
openssl req -newkey rsa:4096 \
            -x509 \
            -sha256 \
            -days 3650 \
            -nodes \
            -out foo.crt \
            -keyout foo.key

方法二

先生成私钥再生成公钥:

1
2
openssl genrsa -out CA.key 4096
openssl req -x509 -new -nodes -key foo.key -sha256 -days 3650 -out foo.crt

就生成公私钥对而言,上述两种方法没有区别。此时的foo.keyfoo.crt已经可以作为SSL证书使用了。

当然,我们也可以把foo.keyfoo.crt作为CA证书,用它们签名子证书,再把签名后的子证书当作SSL证书使用。

这两者的区别在于,只要用户信任了foo.crt,则foo.crt签发的一系列子证书都会被用户信任,在同时为多个网站部署自签名证书时会方便许多。

用CA证书签发子证书

生成子证书的私钥:

1
2
3
4
5
6
7
8
9
# Generate a PKCS#1 key
openssl genrsa -out sub.key 4096

# Or generate a PKCS#8 key
openssl req \
		-newkey rsa:4096 \
        -sha256 \
        -nodes \
        -keyout sub.key

关于PKCS#1 Key和PKCS#8 Key的区别,可以参考 https://stackoverflow.com/questions/20065304/differences-between-begin-rsa-private-key-and-begin-private-key

生成子证书的CSR:

首先,需要创建子证书的扩展文件(Extension File) :

1
2
3
4
5
6
7
8
# v3.ext
[usr_cert]
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment

[SAN]
subjectAltName=DNS:*.sha.azlith.com

然后,使用扩展文件创建CSR:

1
2
# Generate a CSR without SANs
openssl req -new -key sub.key -out sub.csr

当然,也可以把扩展文件的内容通过命令行写入,而不是创建独立的扩展文件:

1
2
3
4
5
6
7
8
openssl req 
		-new \
        -sha256 \
        -days 3650 \
        -reqexts SAN \
        -key huawei.sha.azlith.com.key \
        -out huawei.sha.azlith.com.csr \
        -config <(cat /etc/pki/tls/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:*.sha.azlith.com"))

生成子证书

使用Key、CSR和Extension File生成子证书:

1
2
3
4
5
6
7
8
openssl x509 \
		-days 3650 \
		-in sub.csr \
		-extfile v3.ext \
		-CA ca.crt \
		-CAkey ca.key \
		-CAcreateserial \
		-out sub.crt

或者,像之前那样把扩展文件的内容通过命令行写入:

1
2
3
4
5
6
7
8
9
openssl x509 \
        -days 3650 \
        -in sub.csr \
        -out sub.crt \
        -CA ca.crt \
        -CAkey ca.key \
        -CAcreateserial \
        -extensions SAN \
        -extfile <(cat /etc/pki/tls/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:*.sha.azlith.com")) 

如何判断证书是否可以作为CA证书

通过以下命令,查看CA项的值,可以判断一个证书是否可以作为CA证书使用,即,这个证书是否可以合法地签名其他证书。注意,“是否可以当作CA证书使用”是证书的创建者赋予此证书的内在属性,与“是否是权威CA证书”无关,即使是自签名证书,只要赋予了正确的属性,也可以当作CA证书使用。

1
openssl x509 -noout -text -in <crt file> | grep "X509v3 Basic Constraints: critical" -A 1

无法作为CA证书使用的证书: image.png

可以作为CA证书使用的证书: image.png

注意: 在证书签发阶段,无论用来签名的证书是否可以当作CA证书使用,签发工具(如,openssl)都不会报错。然而,在证书验证阶段,使用无法被当作CA证书的证书签名的证书将被拒绝认证。

参考文献

OpenSSL CA and non CA certificate - Super User

openssl - Creating an x509 v3 user certificate by signing CSR - Stack Overflow

创建自签名CA和SSL证书 - 马谦的博客 (dyxmq.cn)

如何创建自签名SSL证书 | myfreax

使用openssl制作自定义CA、自签名ssl证书 (github.com)