Bootstrap

openssl 正确生成v3带SAN的证书

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。

源码指引:github源码指引_初级代码游戏的博客-CSDN博客


目录

为什么一定要v3和SAN

如何生成v3和SAN

如何确认是v3带SAN的证书

完整脚本参考


为什么一定要v3和SAN

        为什么要v3版本呢?因为v3才能包含扩展。

        为什么一定要包含扩展呢?因为没有扩展就没有SAN。

        为什么一定要SAN呢?因为没有SAN把域名和证书绑定在一起,新版浏览器永远认为不安全。

        如果查看证书详情可能会看到如下信息:

net::ERR_CERT_COMMON_NAME_INVALID

此服务器无法证明它是 www.test.com;它的安全证书不指定使用者可选名称。这可能是由错误配置或者有攻击者截获你的连接而导致的。

         你可能以为这个“common name”不就是CN吗?或许以前如此,现在这个错误实际上指的是SAN,CN已经被废弃了。

        如果证书正确地包含了SAN而访问的域名与SAN不一致,仍然会提示证书问题:

        注意证书的“扩展部分”,对于v1证书是没有这部分的。“证书使用者可选名称”就是SAN,名义上是可选的,事实上是必选的。

        上图中由于SAN只包含两个域名,而访问是用IP地址的,因此不一致,所以浏览器认为服务器证书无效。

        改用域名访问(我已经修改了hosts文件):

         这下浏览器没话说了。

         

如何生成v3和SAN

        openssl默认情况下生成的证书是v1的,要生成v3证书需要在命令行指示使用配置文件的哪个节。

        例如“-extfile $OPEN_SSL_CONFIG_FILE -extensions v3_ca”表示使用$OPEN_SSL_CONFIG_FILE的v3_ca节。

        $OPEN_SSL_CONFIG_FILE代表openssl.cnf文件,可以搜索一下,查看文件,里面应该有v3_ca节,这一节的配置用来生成CA证书。因为这个文件不同安装不一样,而且后面要用好几次,所以设置成变量比较方便。

        v3_req节用来生成普通证书。

        为了生成SAN需要一个独立的节,内容为subjectAltName=域名列表,通过这个把证书和域名绑定在一起(测试的时候可以通过修改hosts文件来把域名解析到自己的IP地址)。最后的完整脚本参考里面用了一点技巧直接在命令行里完成了。

如何确认是v3带SAN的证书

        查看证书文件“openssl x509 -text -noout -in server.cer”:

$ openssl x509 -text -noout -in server.cer
Certificate:
    Data:
        Version: 3 (0x2)======================这是版本,3表示是v3,1表示是v1
        Serial Number:
            35:20:b5:ef:38:32:33:b1:48:30:c5:6d:b0:e5:66:c0:93:3c:2a:24
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = CN, ST = SD, L = JN, O = QDZY, OU = www.test.com, CN = CA, emailAddress = [email protected]
        Validity
            Not Before: Jan 17 09:19:43 2025 GMT
            Not After : Dec 24 09:19:43 2124 GMT
        Subject: C = CN, ST = SD, L = JN, O = QDZY, OU = www.test.com, CN = SERVER, emailAddress = [email protected]
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (2048 bit)
                Modulus:
                    00:9f:eb:d2:fe:9b:3c:c5:81:b6:5d:ca:5c:02:73:
                    e4:b4:64:8b:7c:0e:be:de:6d:29:6a:5a:47:01:27:
                    (略去)
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Alternative Name:==========================这就是SAN
                DNS:www.test.com, DNS:www.test2.com
    Signature Algorithm: sha256WithRSAEncryption
         13:4d:64:21:b6:16:11:62:94:2f:c9:69:df:5c:a1:9a:a4:1e:
         de:ba:72:e9:12:5b:85:cc:37:65:27:a0:39:79:ca:5c:00:f9:
         (略去)

完整脚本参考

#请求证书 openssl.cnf位置可以通过“openssl version -a”查看(OPENSSLDIR) 必须有SAN,否则新版浏览器不认
#为了生成v3证书需要通过-extfile传入配置文件,-extensions指示使用配置文件的哪个节
#注意SAN配置的是域名,可能需要修改hosts文件以便通过域名访问本地服务
export OPEN_SSL_CONFIG_FILE=/usr/lib/ssl/openssl.cnf #根据实际情况修改这个环境变量

#创建CA证书私钥
openssl genrsa -aes256 -out ca.key 2048
#请求证书
openssl req -new -sha256 -key ca.key -out ca.csr -subj "/C=CN/ST=SD/L=JN/O=QDZY/OU=www.test.com/CN=CA/[email protected]"
#自签署证书
openssl x509 -req -days 36500 -sha256 -extfile $OPEN_SSL_CONFIG_FILE -extensions v3_ca -signkey ca.key -in ca.csr -out ca.cer
openssl x509 -text -noout -in ca.cer

#创建服务器私钥
openssl genrsa -aes256 -out server.key 2048
#请求证书
openssl req -new -sha256 -key server.key -out server.csr -subj "/C=CN/ST=SD/L=JN/O=QDZY/OU=www.test.com/CN=SERVER/[email protected]" \
    -reqexts SAN \
    -config <(cat $OPEN_SSL_CONFIG_FILE <(printf "[SAN]\nsubjectAltName=DNS:www.test.com,DNS:www.test2.com\n"))
#查看请求
openssl req  -noout -text -subject -in server.csr

#使用CA证书签署服务器证书
openssl x509 -req -days 36500 -sha256 -extensions v3_req  -CA  ca.cer -CAkey ca.key  -CAserial ca.srl  -CAcreateserial -in server.csr -out server.cer \
    -extensions SAN \
    -extfile <(cat $OPEN_SSL_CONFIG_FILE \
        <(printf "[SAN]\nsubjectAltName=DNS:www.test.com,DNS:www.test2.com\n"))
#查看证书
openssl x509 -text -noout -in server.cer

#生成客户端私钥
openssl genrsa -aes256 -out client.key 2048
#申请证书
openssl req -new -sha256 -key client.key  -out client.csr -subj "/C=CN/ST=SD/L=JN/O=QDZY/OU=www.test.com/CN=CLIENT/[email protected]"
#使用CA证书签署客户端证书
openssl x509 -req -days 36500 -sha256 -extfile $OPEN_SSL_CONFIG_FILE -extensions v3_req  -CA  ca.cer -CAkey ca.key  -CAserial ca.srl  -CAcreateserial -in client.csr -out client.cer
openssl x509 -text -noout -in client.cer

#生成用于windows的pfx证书(pem格式无法导入私钥 注意有些pem里面只有一个证书或key,等价于这里的.key和.cer)
openssl pkcs12 -export -out client.pfx -inkey client.key -in client.cer

#去掉私钥密码
openssl rsa -in ca.key -out ca.key
openssl rsa -in server.key -out server.key
openssl rsa -in client.key -out client.key

#如果提示Can't load /home/user/.rnd into RNG
openssl rand -writerand /home/user/.rnd

(这里是文档结束)

;