制作一份可以被信用的自签名ssl证书
之前有写过一篇简单介绍ssl制作的证书:简单的制作ssl证书,并在nginx和IIS中使用
但是只是简单的制作,发现有个问题,就是哪怕添加到受信任的根证书下也不能被浏览器信任,所以现已重新整理一般可以被浏览器信任的证书制作方式。
首先,我们需要知道,ssl证书可以分为三种类型:根证书、中间证书、服务证书,而证书之间是一种链式结构,使用根证书签署生成中间证书,使用中间证书签署生成服务证书,服务证书提供给应用使用,而根证书和中间证书需要被系统添加到信任列表中。当然,中间证书可以有很多个,也就是中间证书可以签署生成另外一个中间证书,服务证书也可以认为是中间证书的最后一个节点。所以首先我们需要一个根证书,然后一步步签署得到服务证书。
制作根证书
1. 生成根私钥root.key,如果不支持RSA:2048,那么可以使用RSA:1024
openssl genpkey -algorithm RSA:2048 -out root.key
如果报错Algorithm RSA:2048 not found,那么可以使用这个命令生成私钥
openssl genrsa -out root.key 2048
2. 使用根秘钥生成根证书请求root.csr
openssl req -new -key root.key -out root.csr -subj "/C=CN/ST=China/L=Shenzhen/O=Example CA/OU=Software Root/CN=Example Root CA"
这里-subj是证书的一些信息,如果不知道将会在命令执行后逐个输入:
/C=表示两个字符的国家代码,CN表示中国
/ST=国家或者身份全名,China表示中国英文
/L=城市名称
/O=组织名称,比如公司
/OU=组织单位名称,比如公司部分
/CN=通用名称,通常是服务器域名
3. 使用一个临时文件记录拓展信息
echo keyUsage = keyCertSign, cRLSign > .temp.ext
echo basicConstraints=critical,CA:TRUE >> .temp.ext
4. 使用私钥和请求文件签署根证书root.crt,最后删除临时文件
openssl x509 -req -days 36500 -in root.csr -signkey root.key -out root.crt -extfile .temp.ext
rm .temp.ext
其中-days表示有效期天数
到这里我们得到了根证书的三个文件:root.crt、root.csr、root.key。
制作中间证书
现在使用根证书root.crt、root.key来生成中间证书
1. 生成中间证书私钥intermediate.key,如果不支持RSA:2048,那么可以使用RSA:1024
openssl genpkey -algorithm RSA:2048 -out intermediate.key
如果报错Algorithm RSA:2048 not found,那么可以使用这个命令生成私钥
openssl genrsa -out intermediate.key 2048
2. 使用中间证书秘钥生成中间证书请求intermediate.csr
openssl req -new -key intermediate.key -out intermediate.csr -subj "/C=CN/ST=China/L=Shenzhen/O=Example CA/OU=Intermediate Web Security CA/CN=Example Web CA"
上面-subj各参数的含义同根证书
3. 使用一个临时文件记录拓展信息
echo keyUsage = digitalSignature, keyCertSign, cRLSign > .temp.ext
echo basicConstraints=critical,CA:TRUE >> .temp.ext
4. 使用根证书签署生成中间证书intermediate.crt,最后删除临时文件
openssl x509 -req -days 36500 -in intermediate.csr -CA root.crt -CAkey root.key -CAcreateserial -out intermediate.crt -extfile .temp.ext
rm .temp.ext
其中-days表示有效期天数
到这里我们得到了中间证书的三个文件:intermediate.crt、intermediate.csr、intermediate.key。
制作服务证书
首先,我们需要知道我们的证书可以使用的备选名称,也就是访问的域名或者IP地址,然后我们继续
1. 生成服务私钥server.key,如果不支持RSA:2048,那么可以使用RSA:1024
openssl genpkey -algorithm RSA:2048 -out server.key
如果报错Algorithm RSA:2048 not found,那么可以使用这个命令生成私钥
openssl genrsa -out server.key 2048
2. 使用服务秘钥生成根证书请求server.csr
openssl req -new -key server.key -out server.csr -subj "/C=CN/ST=China/L=Shenzhen/O=Example CA/OU=Web Security/CN=example.cn"
上面-subj各参数的含义同根证书
3. 使用一个临时文件记录拓展信息
cat > .temp.ext <<EOF
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName=@SubjectAlternativeName
[SubjectAlternativeName]
IP.1=127.0.0.1
IP.2=192.168.139.128
DNS.1=localhost
DNS.2=example.cn
DNS.3=*.example.cn
EOF
这里SubjectAlternativeName节点下可以理解为就是我们要信任的那些IP和域名,我们把我们需要的写上去就好了,我这边测试用192.168.139.128作为本地虚拟机上的地址验证
4. 使用中间证书签署生成服务证书server.crt,最后删除临时文件
openssl x509 -req -days 36500 -in server.csr -CA intermediate.crt -CAkey intermediate.key -CAcreateserial -out server.crt -extfile .temp.ext
rm .temp.ext
注:这里我们也可以直接采用根证书来生成服务证书,只需要替换上面命令的中间证书和它的私钥即可
openssl x509 -req -days 36500 -in server.csr -CA root.crt -CAkey root.key -CAcreateserial -out server.crt -extfile .temp.ext
到这里我们得到了中间证书的三个文件:server.crt、server.csr、server.key。
证书应用
这里使用Nginx应用为例,比如我们修改Nginx的配置:
server {
listen 80;
listen 443 ssl;
server_name localhost;
# ssl证书相关配置,建议填写证书的全路径
ssl_certificate /etc/nginx/server.crt;
ssl_certificate_key /etc/nginx/server.key;
ssl_session_timeout 5m;
ssl_protocols SSLv3 SSLv2 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;
...省略其它配置
}
重新加载Nginx配置,如果这个时候在未安装证书的时候直接访问,会提示不安全的提示。

所以我们需要安装证书,如果服务证书直接由根证书签署,那么客户端只需要安装根证书(root.crt)即可,否则我们需要安装所有的根证书(root.crt)和中间证书(intermediate.crt)
1. 根证书安装在【受信任的根证书颁发机构】

2. 中间证书安装在【中间证书颁发机构】

3. 安装完成后,我们可以查看我们的服务证书(server.crt)的验证链是否正常(不正常会显示红叉)

然后我们再在浏览器打开我们的应用就可以被信任了

注:如果证书正常,但是还是显示不安全,那么需要把浏览器全部关闭,重新打开浏览器即可
总结
最后总结一下,ssl证书验证过程是链式的,它会逐个验证每个中间证书,直至根证书,有一个验证不通过,则整个验证不通过,所以自签名证书一般只需要一个根证书即可,中间证书一般省略即可,这样只需要安装了根证书,未来我们只需要使用这个根证书签署芯德服务证书,在已经安装了根证书的客户端就可能直接使用了。

浙公网安备 33010602011771号