使用Openssl为Nginx生成证书

我们在企业中,在使用到证书时,一般需要先生成“证书请求”(后缀大多为.csr),它包含你的名字和公钥,然后把这份请求交给诸如verisign等有CA服务公司(当然,连同几百美金),你的证书请求经验证后,CA用它的私钥签名,形成正式的证书发还给你。管理员再在web server上导入这个证书就行了。浏览器内置了很多商业的权威CA,所以你的网站是经过认证的。

而如果在企业内部网站有很多,很有可能公司会自己做CA。公司会先配置CA的私钥和公钥,私钥保存,自签CA,公钥则可以公开。而每个服务器需要生成证书请求提交给公司CA进行签发。这种情况下,访问内部网站时需要自行在客户端需要导入CA证书到受信任的颁发机构。

下面我们将介绍如何生成CA,如果使用CA签名证书,

生成根证书

a).生成根证书私钥(pem文件)

OpenSSL通常使用PEM(Privacy Enbanced Mail)格式来保存私钥,构建私钥的命令如下:

1
2
3
4
5
6
7
openssl genrsa -aes128 -passout pass:CAPassword -out ca.key 1024
该命含义如下:
genrsa——使用RSA算法产生私钥
-aes128 ——使用128位密钥的AES算法对私钥进行加密
-out——输出文件的路径
1024——指定私钥长度

由于Linux系统中可以使用history命令查看历史指令记录,所以出于安全方面的考量,一般不建议在命令中直接使用-passout。这与mysql登录的时候不在 -p选项里直接指定登录口令的原因是一致的。本文只是为了演示使用。

b).生成根证书签发申请文件(csr文件)

使用上一步生成的私钥(pem文件),生成证书请求文件(csr文件):

1
2
3
4
5
6
7
8
9
10
openssl req -sha256 -new -key ca.key -out ca.csr \
-subj "/C=CN/ST=GuangDong/L=ShenZhen/O=Company/OU=Dept/CN=Name" -passin pass:CAPassword
该命令含义如下:
req——执行证书签发命令
-new——新证书签发请求
-key——指定私钥路径
-out——输出的csr文件的路径
-subj——证书相关的用户信息(subject的缩写),其中CN一般填写机器IP
-passin ——加入后可以代入CA密码,不加需要手动输入

c).自签发根证书(cer文件)

csr文件生成以后,我们需要将其发送给CA认证机构进行签发,这样证书才有权威性。而认证机构是需要收费的,所以,这里我们仅做测试,我们对自己的证书生成文件进行自签发:

1
2
3
4
5
6
7
8
9
10
11
12
openssl x509 -req -days 3650 -sha256 -extensions v3_ca \
-signkey ca.key -in ca.csr -out ca.cer -passin pass:CAPassword
该命令的含义如下:
x509——生成x509格式证书
-req——输入csr文件
-days——证书的有效期(天)
-sha256——证书摘要采用sha256算法
-extensions——按照openssl.cnf文件中配置的v3_ca项添加扩展
-signkey——签发证书的私钥
-in——要输入的csr文件
-out——输出的cer证书文件

生成服务端证书

在实际使用时,如果是对外(客户)使用,我们对外提供的每一个网站,都需要使用权威机构签发的证书进行签发。一个证书可以包含企业的很多域名,例如百度的证书如下。

1
2
3
Subject: C=CN, ST=beijing, L=beijing, OU=service operation department, O=Beijing Baidu Netcom Science Technology Co., Ltd, CN=baidu.com
X509v3 Subject Alternative Name:
DNS:baidu.com, DNS:baifubao.com, DNS:www.baidu.cn, DNS:www.baidu.com.cn, DNS:click.hm.baidu.com, DNS:log.hm.baidu.com, DNS:cm.pos.baidu.com, DNS:wn.pos.baidu.com, DNS:update.pan.baidu.com, DNS:mct.y.nuomi.com, DNS:*.baidu.com, DNS:*.baifubao.com, DNS:*.baidustatic.com, DNS:*.bdstatic.com, DNS:*.bdimg.com, DNS:*.hao123.com, DNS:*.nuomi.com, DNS:*.chuanke.com, DNS:*.trustgo.com, DNS:*.bce.baidu.com, DNS:*.eyun.baidu.com, DNS:*.map.baidu.com, DNS:*.mbd.baidu.com, DNS:*.fanyi.baidu.com, DNS:*.baidubce.com, DNS:*.mipcdn.com, DNS:*.news.baidu.com, DNS:*.baidupcs.com, DNS:*.aipage.com, DNS:*.aipage.cn, DNS:*.bcehost.com, DNS:baifae.com, DNS:*.safe.baidu.com, DNS:*.im.baidu.com, DNS:*.ssl2.duapps.com, DNS:*.baifae.com, DNS:*.baiducontent.com, DNS:*.dlnel.com

但是,在企业内部,如果我们内部的网站够多,我们往往自己生成一个根证书(或者用外部权威机构签发一个二级CA),用这个根证书再去签发内部的各种服务端。一般这种场景才会有下面的步骤,而如果只是对外使用,使用权威机构签发的证书,直接进行nginx或tomcat等容器的配置就可以了。

a).生成服务端证书私钥(pem文件)

1
openssl genrsa -aes128 -passout pass:ServerPassword -out server.key 2048

b).生成成服务端证书签发申请文件(csr文件)

1
2
openssl req -new -sha256 -key server.key -out server.csr \
-subj "/C=CN/ST=GuangDong/L=ShenZhen/O=Company/OU=Dept/CN=localhost" -passin pass:ServerPassword

-subj——证书相关的用户信息(subject的缩写),其中CN一般填写服务端的机器IP或域名,我们这里在本地测试,所以填写localhost

c).使用根证书签发服务端证书

我们使用已经找CA(权威结构)认证过的根证书(其实找CA认证是花钱的,我们使用的是自己签发的证书)对该证书进行签发:

1
2
3
4
5
6
7
8
openssl ca -in server.csr -out server.crt -passin pass:CAPassword \
-cert cacert.pem -keyfile cakey.pem \
-days 3650 -extensions v3_req
# 或者使用以下指令
openssl x509 -req -days 3650 -sha256 -extensions v3_req \
-CA ca.cer -CAkey ca.key -CAserial ca.srl -CAcreateserial \
-passin pass:CAPassword -in server.csr -out server.crt

1
2
3
4
5
这里有必要解释一下这几个参数:
-CA——指定CA证书的路径
-CAkey——指定CA证书的私钥路径
-CAserial——指定证书序列号文件的路径
-CAcreateserial——表示创建证书序列号文件(即上方提到的serial文件),创建的序列号文件默认名称为-CA,指定的证书名称后加上.srl后缀

为nginx开启https,并配置证书

1
2
3
4
5
6
server {
listen 443 ssl;
ssl_certificate ssl/server.crt;
ssl_certificate_key ssl/server.key;
}

核心配置只有三行,也可以采用ssl on来配置。
不过配置证书后,每次重启、重载nginx都要输入私钥密码,可以输入以下命令:

1
openssl rsa -in server.key -passin pass:ServerPassword -out server.key.unsecure

导出无密码的私钥,生产环境这么做有安全风险,需谨慎,一般可以通过脚本文件生成解密的密钥后再重载,重载完成后,再对解密的私钥文件进行删除

配置后我们就能够使用https来访问自己的页面了。但是访问的时候,如果我们的服务端使用自己生成的CA签发的证书,那么浏览器会提示我们,网站存在风险。下面我们需要导出证书到windows客户端进行安装。

导出证书到windows客户端进行安装

我们可以使用如下命令把证书导出为PKCS12格式:

1
2
3
4
5
openssl pkcs12 -export -out ca.p12 -inkey ca.key -in ca.cer
Enter pass phrase for ca.key:
Enter Export Password:
Verifying - Enter Export Password:

导出需要输入CA的私钥,以及输入两次导出密码(下面再windows上导入证书的时候需要使用)。

导出后,将ca.p12复制到windows环境,双击安装,输入密码,最后选择导入证书到 受信任的证书颁发机构即可。

最后再次访问可以发现网站风险已经消除。

出现问题记录

1, unable to load number from /etc/pki/CA/serial error while loading serial number

1
2
3
touch /etc/pki/CA/index.txt
touch /etc/pki/CA/serial
echo "01" > serial # 首次必须添加序列号否则会报错

其他:证书校验方法和证书格式转换命令

1,证书校验方法

1
2
3
4
5
6
7
8
9
10
11
12
13
# 使用CA证书校验身份证书是否合法
openssl verify -CAfile ca.cer server.cer
# 校验身份证书和私钥文件是否匹配(通过校验身份证书和私钥文件的modulus是否一致)
openssl x509 -in 身份证书 -modulus -noout
openssl rsa -in 私钥文件 -passin pass:私钥口令
openssl x509 -in server.cer -modulus -noout
openssl rsa -in server.key -modulus -noout -passin pass:ServerPassword
# 校验p12证书是否为当前CA签发,可以通过将p12证书导出PEM格式身份证书,再通过1中的方法校验
openssl pkcs12 -in 身份证书 -nokeys -passin pass:导入口令

2,证书转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 根据server.cer(证书)和server.key(私钥)生成p12证书(server.p12):
openssl pkcs12 -export -aes128 {-descert} -in server.cer -inkey server.key -out server.p12 -passin pass:ServerPassword {-passout pass:P12Password} {-certfile ca.cer}
该命令的含义如下:
-export——导出pkcs12格式
-descert——使用3DES加密证书
-in——证书文件
-inkey——私钥文件
-passin——私钥密码
-out——输出的pkcs12文件
-passout——pkcs12文件导出密码,如果不指定该命令,则要求输入,不输入两次回车表示不加密码
-certfile——导出的证书带有CA证书
# 根据p12证书(server.p12)分解成server.cer和server.key:
把p12格式转换为可读格式
openssl pkcs12 -in server.p12 -out server.p12.pem
---如果不想导出私钥,可加-nokeys
---如果不想加密私钥,可加-nodes
---如果不想导出证书,可加-nocerts
所以从p12文件中提取证书(.cer)
openssl pkcs12 -in server.p12 -out server.out.cer -nokeys
PFX文件中提取私钥(.key)
openssl pkcs12 -in server.p12 -nocerts -nodes -out server.out.key
PEM BASE64转为X.509文本格式
openssl x509 -in Key.pem -text -out cert.pem

参考

  1. 使用openssl进行证书格式转换
  2. 如何使用OpenSSL工具生成根证书与应用证书
  3. OpenSSL生成根证书CA及签发子证书
  4. OpenSSL使用2(SSL,X.509,PEM,DER,CRT,CER,KEY,CSR,P12概念说明)(转)
  5. 使用 OpenSSL 实现私钥和证书的转换
  6. 一次加密通信和SSL通信,openssl自建CA
分享到