OpenSSL的详细使用
# OpenSSL的使用
# 原理、流程与示例
# 1.1 生成证书的步骤与原理
要理解创建证书的每一步操作必须要先理解创建证书的流程和每一步的含义。生成证书的标准流程是这样的:
- 生成自己的私钥文件
(.key)
- 基于私钥生成证书请求文件
(.csr)
- 将证书请求文件(.csr)提交给证书颁发机构(CA),CA会对提交的证书请求中的所有信息生成一个摘要,然后使用CA根证书对应的私钥进行加密,这就是所谓的“签名”操作,完成签名后就会得到真正的签发证书(.cer或.crt)用户拿到签发后的证书,可能需要导入到自己的密钥库中,如Java的keystore,或根据需要再进行各种格式转换
(.pem .p12 .jks等等)
注意:
- 第1/2两步可以通过一个命令合并完成。
- 第3步向公认可信的CA机构申请证书是线上线下都要进行操作的一系列流程,申请的公司或组织还要提交各种资质和证明,与企业申请某种执照或办理某种手续性质类似,但企业最终拿到的就是一个CA签名的证书文件。所以,对于企业内部应用来说,完全可以自己创建自己的根证书,自己给自己签发证书,然后通过域控手段强制用户浏览器接受来自相应CA签发的证书。
- 再次解释一下“签名”的含义,这个概念很关键。在CA签发的证书中,包含申请者的公钥在内,几乎所有的数据都是明文的,也都是申请者自己提供的(当然CA需要审核),签发的证书唯一多出来的信息就是基于申请者提供的所有信息生成了一份摘要,然后用CA自己的私钥对摘要进行了加密,这段加密后的密文被称之为“签名”,这部分数据是返还的签发证书(.cer或.crt)中多出来的关键数据。下图是CA签发证书的原理:
汇总所有的情况来看,生成证书不外乎三种情形:
- 标准CA签发流程
- 生成自签名证书
- 生成私有CA签发的证书
对于绝大多数的开发者而言,需要使用的其实是后两种:自签名证书和私有CA签发的证书。对这两种证书的差异,笔者现在理解的还不沟透彻,需要进一步研究。网上的说法是:自签名证书无法被吊销,私有CA签发的证书可以被吊销。从它们各自的命令行工具上看,后者确实有一个撤销操作openssl ca -revoke。此外,生成这两种证书的命令也是不一样的。
针对私有CA签发的证书,网上有如下的建议:
如果你的规划需要创建多个证书,那么使用私有CA的方法比较合适,因为只要给所有的客户端都安装了CA的证书,那么以该证书签名过的证书,客户端都是信任的,也就是安装一次就够了
如果你直接用自签名证书,你需要给所有的客户端安装该证书才会被信任,如果你需要第二个证书,则还的挨个给所有的客户端安装证书2才会被信任。
# 1.2 标准的CA签发流程
对应文章开头提及的证书生成流程,标准CA签发流程中的第三步是需要CA机构操作的,我们会解释CA机构要做的工作。
# 1.2.1 创建私钥(.key)
openssl genrsa -out my.key 2048
# 1.2.2 创建证书签名请求(.csr)
要基于私钥创建证书签名请求
openssl req -new -key my.key -out my.csr -subj "/C=CN/ST=shanghai/L=shanghai/O=example/OU=it/CN=domain1/CN=domain2"
# 或者
root@fisco-server-2:~/ssl# openssl req -new -days 36500 -key server.key -out server.csr
Ignoring -days; not generating a certificate
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CN ##国家地区
State or Province Name (full name) [Some-State]:HS ##省份名称
Locality Name (eg, city) []:ShangHai ##城市名称
Organization Name (eg, company) [Internet Widgits Pty Ltd]:BTC ##组织名称
Organizational Unit Name (eg, section) []:ops ##组织单位名称
Common Name (e.g. server FQDN or YOUR name) []:zyh ##域名
Email Address []:zyh@163.com ## 邮箱
Please enter the following 'extra' attributes # 添加一个而外的密码,请问文件时需要输入的,所以可有可无
to be sent with your certificate request
A challenge password []:
An optional company name []:
# 1.2.3 生成私钥和证书签名请求
两个关键参数:
- -newkey rsa:2048 -> 生成一个新的证书签名请求,同时生成一个2048位的RSA私钥
- -nodes -> 不对新私钥加密
openssl req -new -newkey rsa:2048 -nodes -keyout my.key -out my.csr -subj "/C=CN/ST=shanghai/L=shanghai/O=example/OU=it/CN=domain1/CN=domain2"
将证书申请请求(.csr)提交给CA认证机构申请证书(.crt):
- 但是在CA机构那里,执行人员一定会使用CA自己的密钥对CSR进行签名操作,这一步操作与我们将在第4节介绍的使用私有CA证书对应的私钥进行签名性质上是一样的。
- 从CSR到CRT,就是一个签名过程,这个过程需要用签发方的私钥。走标准CA签发流程,是CA机构来操作,用的是他的根证书对应的私钥来签名;走自签名证书或私有CA证书的流程,用的就是自己的私钥。
# 1.3 生成自签证书
# 1.3.1 创建私钥(.key)
openssl genrsa -out my.key 2048
# 1.3.2 创建证书签名请求(.csr)
openssl req -new -key my.key -out my.csr -subj "/C=CN/ST=shanghai/L=shanghai/O=example/OU=it/CN=domain1/CN=domain2"
# 1.3.3 生成自签名证书(.crt)
对于这条命令,要注意以下几点:
- 这个命令是
openssl x509
,-req
是参数,和前面生成证书签名请求的openssl req
命令不同。 -signkey my.key
配置清晰地表明使用自己的私钥进行签名。
openssl x509 -req -in my.csr -out my.crt -signkey my.key -days 3650
# 1.4 生成私有CA签发的证书
与生成自签名证书不同地方在于,生成自签名证书场景下只有一个参与方,请求证书和签发证书都是自己,而生成私有CA证书的场景里开始涉及两个角色了:
- 签发证书的一方:CA(主要牵涉的是CA私钥和根证书)
- 请求签发证书的一方:如服务器
为了变于区别,我们把它相关的文件分别用ca和server加以区别
# 1.4.1 生成CA的私钥签名证书
openssl req -x509 -newkey rsa:2048 -nodes -keyout ca.key -out ca.crt -days 3650 -subj "/C=CN/ST=shanghai/L=shanghai/O=example/OU=it/CN=domain1/CN=domain2"
# 1.4.2 生成Server的私钥签名请求
openssl req -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr -subj "/C=CN/ST=shanghai/L=shanghai/O=example/OU=it/CN=domain1/CN=domain2"
# 1.4.3 使用CA签名证书
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 3650
关于-CAcreateserial
- 当签署证书时,CA 需要为每个证书生成一个唯一的序列号,由于每个证书的序列号对于每个颁发者都必须是唯一的,因此颁发者需要跟踪它以前使用过哪些序列号,以确保它不会重复使用任何序列号。OpenSSL 提供了一种使用序列号文件进行跟踪的简单方法。当你指定 -CAcreateserial 时,它会将序列号 01 或一个随机数分配给签名证书,然后创建此序列号文件。在未来的签名操作中,应该使用 -CAserial 和该文件的名称,而不是-CAcreateserial,并且 OpenSSL 将为每个签名的证书增加该文件中的值。这样,你可以用一个颁发者证书签署一堆证书,并且它们的所有序列号都是唯一的。
# 1.5 openssl req命令
由于创建证书的关键命令是openssl req命令,此处特别罗列一个这个命令的关键参数。
# 1.5.1 命令详解
-days <n>
指定证书有效期,默认是30天,与 -x509 选项一起使用
-newkey rsa:2048
生成一个新的证书申请,同时生成一个 2048 位的 RSA 私钥
-keyout <keyfile>
新私钥要写入的文件
-nodes
不对新私钥加密
-key <keyfile>
读取指定的私钥文件.
-text
同时打印纯文本版本和编码版本信息
-noout
不打印编码后版本 (BASE64编码)
-new
生成一个新的证书申请,会提示用户输入相关字段的值,如果没有 -key 选项,会使用指定配置文件中的信息生成一个新的 RSA 私钥.
-x509
输出自签名的证书,而不是请求一个证书. 通常用于生成测试证书或自签名的根证书.
-subj <arg>
申请人信息,格式是 /C=CN/O=Corp/.../CN=www.ez.com,可以使用 \ 转义,不会跳过空格.
-[digets] 指定签署请求时使用的信息摘要算法,如 -md5,-sha1,-sha256
# 1.5.2 -subj
参数
/C= Country 国家
/ST= State or Province 省
/L= Location or City 城市
/O= Organization 组织或企业
/OU= Organization Unit 部门
/CN= Common Name 域名或IP
# 1.6 完整创建流程
操作系统 | OpenSSL版本 |
---|---|
Ubuntu | 1.1.1 |
# 1.6.1 配置OpenSSL
root@server-2:~# vim /etc/ssl/openssl.cnf
####################################################################
[ ca ]
default_ca = CA_default # The default ca section
####################################################################
[ CA_default ]
dir = /root/ssl/ # 设置一个存放证书的目录
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
#unique_subject = no # Set to 'no' to allow creation of
# several certs with same subject.
new_certs_dir = $dir/newcerts # default place for new certs.
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
x509_extensions = usr_cert # The extensions to add to the cert
# Comment out the following two lines for the "traditional"
# (and highly broken) format.
name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options
####################################################################
[ tsa ]
default_tsa = tsa_config1 # the default TSA section
[ tsa_config1 ]
# These are used by the TSA reply generation only.
dir = /root/ssl # TSA的根目录
serial = $dir/tsaserial # The current serial number (mandatory)
crypto_device = builtin # OpenSSL engine to use for signing
signer_cert = $dir/tsacert.pem # The TSA signing certificate
# (optional)
certs = $dir/cacert.pem # Certificate chain to include in reply
# (optional)
signer_key = $dir/private/tsakey.pem # The TSA private key (optional)
signer_digest = sha256 # Signing digest to use. (Optional)
default_policy = tsa_policy1 # Policy if request did not specify it
# (optional)
# 1.6.2 开始创建证书
root@server-2:~# pwd
/root/ssl
# 创建CA私钥
root@server-2:~# openssl genrsa -out CA.key 2048
# 制作CA公钥
root@server-2:~# openssl req -sha256 -new -x509 -days 36500 -key CA.key -out CA.crt -config /etc/pki/tls/openssl.cnf
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:SH
Locality Name (eg, city) [Default City]:ShangHai
Organization Name (eg, company) [Default Company Ltd]:BTC
Organizational Unit Name (eg, section) []:LAYZER
Common Name (eg, your name or your server's hostname) []:LayzerSign CA
Email Address []:layzer@163.com
# 当然上述的公钥制作方式需要交互式输入信息,如果不想频繁输入,那么可以使用如下命令:
openssl req -sha256 -new -x509 -days 36500 -key CA.key -out CA.crt -config /etc/pki/tls/openssl.cnf -subj "/C=CN/ST=SH/L=ShangHai/O=BTC/OU=LAYZER/CN=LayzerSign CA/emailAddress=layzer@163.com"
# 上面做完之后我们看看现在我们的到了什么
[root@virtual_host ssl]# ls
CA.crt CA.key
# 1.6.3 自签证书
#我们的操作步骤为:
1:生成域名私钥
2:生成证书签发请求文件
3:使用自签署的CA,生成域名公钥
# 1:生成 layzer.com.key 密钥
root@server-2:~# openssl genrsa -out layzer.com.key 2048
# 2:生成 layzer.com.csr 证书签发请求 交互式
root@server-2:~# openssl req -new -sha256 -key layzer.com.key -out layzer.com.csr -config /etc/pki/tls/openssl.cnf
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:SH
Locality Name (eg, city) [Default City]:ShangHai
Organization Name (eg, company) [Default Company Ltd]:BTC
Organizational Unit Name (eg, section) []:LAYZER
Common Name (eg, your name or your server's hostname) []:*.layzer.com # 这个就是要申请的泛域名
Email Address []:layzer@163.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:123456
An optional company name []:BTC
# 当然了这个也有非交互式
openssl req -new -sha256 -key layzer.com.key -out layzer.com.csr -config /etc/pki/tls/openssl.cnf -subj "/C=CN/ST=SH/L=ShangHai/O=BTC/OU=LAYZER/CN=*.layzer.com/emailAddress=layzer@163.com"
# 查看签名请求文件信息
root@server-2:~# openssl req -in layzer.com.csr -text
# 使用自签署的CA,签署layzer.com.crt
root@server-2:~# openssl ca -in layzer.com.csr -md sha256 -days 36500 -out layzer.com.crt -cert CA.crt -keyfile CA.key -config /etc/pki/tls/openssl.cnf
# 当然了,我们可能会遇到如下报错
Using configuration from /etc/pki/tls/openssl.cnf
/etc/pki/CA/index.txt: No such file or directory
unable to open '/etc/pki/CA/index.txt'
140216322066320:error:02001002:system library:fopen:No such file or directory:bss_file.c:402:fopen('/etc/pki/CA/index.txt','r')
140216322066320:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:404:
# 解决方法如下:
root@server-2:~# touch /etc/pki/CA/index.txt
# 还有另外的报错:
Using configuration from /etc/pki/tls/openssl.cnf
/etc/pki/CA/serial: No such file or directory
error while loading serial number
140152413099920:error:02001002:system library:fopen:No such file or directory:bss_file.c:402:fopen('/etc/pki/CA/serial','r')
140152413099920:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:404:
# 解决方法如下:
root@server-2:~# echo "01" > /etc/pki/CA/serial
[root@virtual_host ssl]# openssl ca -in layzer.com.csr -md sha256 -days 36500 -out layzer.com.crt -cert CA.crt -keyfile CA.key -config /etc/pki/tls/openssl.cnf
Using configuration from /etc/pki/tls/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 1 (0x1)
Validity
Not Before: Aug 20 17:39:16 2022 GMT
Not After : Jul 27 17:39:16 2122 GMT
Subject:
countryName = CN
stateOrProvinceName = SH
organizationName = BTC
organizationalUnitName = LAYZER
commonName = *.layzer.com
emailAddress = layzer@163.com
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
46:F3:0D:B9:6B:7F:4C:6B:C0:F6:CE:47:F8:E6:39:9E:09:F9:2F:69
X509v3 Authority Key Identifier:
keyid:9B:E9:58:13:45:7F:EF:7D:92:7D:AE:73:09:A3:9A:77:99:16:3E:30
Certificate is to be certified until Jul 27 17:39:16 2122 GMT (36500 days)
Sign the certificate? [y/n]:y # 输入y确认
1 out of 1 certificate requests certified, commit? [y/n]y # 输入y确认
Write out database with 1 new entries
Data Base Updated
# 检查部署是否正常
root@server-2:~# cat /etc/pki/CA/index.txt
V 21220727173916Z 01 unknown /C=CN/ST=SH/O=BTC/OU=LAYZER/CN=*.layzer.com/emailAddress=layzer@163.com
root@server-2:~# cat /etc/pki/CA/serial
02
# 这证明我们的证书颁发已经被记录了。
# 注:同一个域名不能签署多次;由于签署了*.layzer.com,且已经被记录,因此不能再次被签署。除非删除该记录。
# 注:注意index.txt文件和serial文件的关系。serial文件内容为index.txt文件内容行数加1。
# 查看证书信息
root@server-2:~# openssl x509 -in layzer.com.crt -text
# 验证签发证书是否有效
root@server-2:~# openssl verify -CAfile CA.crt layzer.com.crt
layzer.com.crt: OK
# 看看目前我们有什么
root@server-2:~# ll
total 24
-rw-r--r-- 1 root root 1399 Aug 20 13:27 CA.crt
-rw-r--r-- 1 root root 1675 Dec 27 2021 CA.key
-rw-r--r-- 1 root root 4576 Aug 20 13:39 layzer.com.crt
-rw-r--r-- 1 root root 1041 Aug 20 13:35 layzer.com.csr
-rw-r--r-- 1 root root 1675 Aug 20 13:31 layzer.com.key
# 转换证书给Nginx使用
root@server-2:~# openssl x509 -in layzer.com.crt -out layzer.com.pem -outform PEM
root@server-2:~# ll
total 28
-rw-r--r-- 1 root root 1399 Aug 20 13:27 CA.crt
-rw-r--r-- 1 root root 1675 Dec 27 2021 CA.key
-rw-r--r-- 1 root root 4576 Aug 20 13:39 layzer.com.crt
-rw-r--r-- 1 root root 1041 Aug 20 13:35 layzer.com.csr
-rw-r--r-- 1 root root 1675 Aug 20 13:31 layzer.com.key
-rw-r--r-- 1 root root 1419 Aug 20 13:44 layzer.com.pem
# 1.6.4 测试证书
root@server-2:~# mkdir /etc/nginx/ssl
root@server-2:~# cp layzer.com.pem layzer.com.key /etc/nginx/ssl/
server {
listen 80;
server_name layzer.com;
location /{
return 301 https://layzer.com;
}
}
server {
listen 443 ssl http2;
server_name layzer.com;
root /usr/share/nginx/html;
index index.html;
ssl_certificate /etc/nginx/ssl/layzer.com.pem;
ssl_certificate_key /etc/nginx/ssl/layzer.com.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
}
上次更新: 2023/11/28, 22:03:59