HTTPS与数字证书(5)-openssl制作证书详细教程

549 阅读5分钟

操作环境:Win10

1. openssl工具的安装

下载地址:slproweb.com/products/Wi…

本着用新不用旧的想法,直接上最新版。Win64 OpenSSL v3.0.7 Win32 OpenSSL v3.0.7

Tips:1、msi和exe文件的区别

2、Light版本,最常用的基本要素(OpenSSL创建者建议用户使用)

3、非Light版本,功能最全(OpenSSL创建者建议软件开发人员使用)

具体安装步骤见该博客 Windows平台安装OpenSSL,或者自行百度。

2. openssl工具的了解

2.1 数字证书格式

.pem 是一种容器格式,可以将服务端证书(server certificate),中间证书(intermediate certificate)和私钥(private key)包含在一个文件中。用于存储和发送加密密钥,证书和其他数据。可能仅包含公钥证书,也可以包含完整的证书链(包括公玥,私钥,和根证书)。跟crt/cer的区别是它以Ascii来表示。

.key 其实就是一个pem格式只包含私玥的文件,.key 作为文件名只是作为一个明显的别名。

.cer 后缀的证书文件有两种编码 --> DER二进制编码或者BASE64编码(也就是.pem)

.cer/.crt 是用于存放证书,它是二进制形式存放的,不含私钥。

p7b 一般是证书链,里面包括1到多个证书

.pfx 是指以pkcs#12格式存储的证书和相应私钥。这类证书主要使用在Windows平台。

pfx/p12 用于存放个人证书/私钥,他通常包含保护密码,2进制方式

IOS证书: .cer格式,二进制编码 Android证书: .crt格式,base64编码

详见博客:

数字证书各种格式解释

搞懂 PEM、ANS、PFX、P12、p8、CER、X509 等证书相关文件格式 后缀

2.2 证书管理目录

这是openssl对于数字证书管理提供的管理目录。主要搞明白这些文件和目录,然后和配置文件中选项对应起来就可以了。 也不一定非要按照这个目录去存放,只要你觉得不混乱,想怎么放怎么放。 在我的实践中,只有生成SAN证书和吊销证书列表时才考虑使用配置文件,否则不如命令行直接指定来的便捷。

dir = ./demoCA        # 保存所有信息的文件夹
$dir/certs            # 保存已生成证书的文件夹
$dir/crl              # 保存吊销证书的文件夹
$dir/index.txt        # 保存签发证书的文本数据库文件
$dir/newcerts         # 保存新签发证书的默认目录,文件后缀是.pem
$dir/cacert.pem       # 保存CA本身根证书的文件名
$dir/serial           # 签发证书时使用的序列号文本文件,里面必须包含下一个可用的16进制数字
$dir/crlnumber        # 存放当前CRL编号的文件
$dir/crl.pem          # 当前crl文件
$dir/private/cakey.pem # 存放CA自身私钥的文件名

3. openssl命令行生成证书(简单,不涉及X509扩展字段信息)

说明:命令行生成是不包含数字证书的扩展信息的,如需要生成更全面的数字证书,请使用配置文件生成

subj参数说明:
/C=CN        # Country 国家
/ST=beijing  # State or Province 省
/L=beijing   # Location or City 城市
/O=huawei    # Organization 组织或企业
/OU=huawei   # Organization Unit 部门
/CN=huawei   # Common Name 域名或IP

示例:-subj "/C=CN/ST=beijing/L=beijing/O=huawei/OU=huawei/CN=localhost"

3.1 生成根CA证书私钥 (.key)

openssl genrsa -aes256 -passout pass:123456 -out rootCA_private.key 2048

3.2 生成根CA证书请求文件(.csr)

openssl req -new -key rootCA_private.key -passin pass:123456 -out rootCA.csr -subj "/C=CN/ST=beijing/L=beijing/O=huawei/OU=huawei/CN=rootCA"

3.3 生成根CA自签证书 (.crt)

openssl x509 -req -in rootCA.csr -signkey rootCA_private.key -passin pass:123456 -out rootCA.crt

3.4 生成服务器证书私钥 (.key)

openssl genrsa -aes256 -passout pass:123456 -out server_private.key 2048

3.5 生成服务器证书请求文件(.csr)

openssl req -new -key server_private.key -passin pass:123456 -out server.csr -subj "/C=CN/ST=beijing/L=beijing/O=huawei/OU=huawei/CN=localhost"

3.6 生成服务器证书,用根CA证书签发 (.crt)

openssl x509 -req -days 365 -in server.csr -CA rootCA.crt -CAkey rootCA_private.key -passin pass:123456 -CAcreateserial -out server.crt

3.4 生成客户端证书私钥 (.key)

openssl genrsa -aes256 -passout pass:123456 -out client_private.key 2048

3.5 生成客户端证书请求文件(.csr)

openssl req -new -key client_private.key -passin pass:123456 -out client.csr -subj "/C=CN/ST=beijing/L=beijing/O=huawei/OU=huawei/CN=客户端IP"

3.6 生成客户端证书,用根CA证书签发 (.crt)

openssl x509 -req -days 365 -in client.csr -CA rootCA.crt -CAkey rootCA_private.key -passin pass:123456 -CAcreateserial -out client.crt

4. openssl使用配置文件生成 SAN数字证书

配置文件内容详解见博客

OpenSSL之七:openssl.cnf

OpenSSL主配置文件openssl.cnf

openssl配置文件

根据实际情况创建openssl.cnf文件,完成配置选项。

[ v3_req_server ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names_server

[ alt_names_server ]
# 解析域名
DNS.1 = localhost
# 可配置多个域名,如下
# DNS.2 = *.example.com
# IP地址(服务器或客户端的IP地址)
IP.1 = 10.112.30.145


[ v3_req_client ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names_client

[ alt_names_client ]
# IP地址(服务器或客户端的IP地址)
IP.1 = 10.112.30.145

4.1 生成根CA证书私钥 (.key)

openssl genrsa -aes256 -passout pass:123456 -out rootCA_private.key 2048
openssl rsa -in rootCA_private.key -passin pass:123456 -noout -text

4.2 生成根CA证书请求文件(.csr)

openssl req -new -key rootCA_private.key -passin pass:123456 -out rootCA.csr -subj "/C=CN/ST=beijing/L=beijing/O=huawei/OU=huawei/CN=rootCA"
openssl req -in rootCA.csr -noout -text

4.3 生成根CA自签证书 (.crt)

openssl x509 -req -in rootCA.csr -signkey rootCA_private.key -passin pass:123456 -out rootCA.crt
openssl x509 -in rootCA.crt -noout -text

4.4 生成服务器证书私钥 (.key)

openssl genrsa -aes256 -passout pass:123456 -out server_private.key 2048

4.5 生成服务器证书请求文件(.csr)

openssl req -new -key server_private.key -passin pass:123456 -out server.csr -subj "/C=CN/ST=beijing/L=beijing/O=huawei/OU=huawei/CN=localhost"

4.6 生成服务器证书,用根CA证书签发 (.crt)

openssl x509 -req -days 365 -in server.csr -CA rootCA.crt -CAkey rootCA_private.key -passin pass:123456 -CAcreateserial -out server.crt -extfile openssl.cnf -extensions v3_req_server
openssl x509 -in server.crt -noout -text

4.4 生成客户端证书私钥 (.key)

openssl genrsa -aes256 -passout pass:123456 -out client_private.key 2048

4.5 生成客户端证书请求文件(.csr)

openssl req -new -key client_private.key -passin pass:123456 -out client.csr -subj "/C=CN/ST=beijing/L=beijing/O=huawei/OU=huawei/CN=10.112.30.145"

4.6 生成客户端证书,用根CA证书签发 (.crt)

openssl x509 -req -days 365 -in client.csr -CA rootCA.crt -CAkey rootCA_private.key -passin pass:123456 -CAcreateserial -out client.crt -extfile openssl.cnf -extensions v3_req_client
openssl x509 -in client.crt -noout -text

5. openssl生成证书后转换成.jks

根证书存储到文件

# 根证书存储到jks文件
keytool -importcert -alias rootCA -keystore rootCA.jks -storepass 123456 -file rootCA.crt
# 查看jks文件内容
keytool -list -keystore rootCA.jks -storepass 123456 -v

私钥+证书合并到一个文件

# 私钥+证书合并到一个文件
openssl pkcs12 -export -passout pass:123456 -out server.pfx -inkey server_private.key -passin pass:123456 -in server.crt
# pfx转换为jks命令
keytool -importkeystore -srckeystore server.pfx -srcstorepass 123456 -srcstoretype pkcs12 -destkeystore server.jks -deststorepass 123456 -deststoretype jks
# 查看jks文件内容
keytool -list -keystore server.jks -storepass 123456 -v

6. openssl生成无效证书(用于测试)

5.1 生成过期证书

# 生成服务器证书私钥(pem)
openssl genrsa -aes256 -passout pass:123456 -out server_private_expired.key 2048
# 生成服务器证书请求文件(.csr)
# 增加x509拓展字段信息(域名/IP)
openssl req -new -key server_private_expired.key -passin pass:123456 -out server_expired.csr -subj "/C=CN/ST=beijing/L=beijing/O=huawei/OU=huawei/CN=localhost"
openssl req -in server_expired.csr -noout -text
# 生成服务器证书,用根CA证书签发(csr)
openssl x509 -req -days -1 -in server_expired.csr -CA rootCA.crt -CAkey rootCA_private.key -passin pass:123456 -CAcreateserial -out server_expired.crt -extfile openssl.cnf -extensions v3_req_server
openssl x509 -in server_expired.crt -noout -text
# 私钥+证书合并到一个文件
openssl pkcs12 -export -passout pass:123456 -out server_expired.pfx -inkey server_private_expired.key -passin pass:123456 -in server_expired.crt
# pfx转换为jks命令
keytool -importkeystore -srckeystore server_expired.pfx -srcstorepass 123456 -srcstoretype pkcs12 -destkeystore server_expired.jks -deststorepass 123456 -deststoretype JKS
# 查看jks文件内容
keytool -list -keystore server_expired.jks -storepass 123456 -v


5.2 生成域名不匹配证书

# tips:(优先修改配置文件DNS.1 = www.localhost.com)
# 生成服务器证书私钥(pem)
openssl genrsa -aes256 -passout pass:123456 -out server_private_DNSError.key 2048
# 生成服务器证书请求文件(.csr)
# 增加x509拓展字段信息(域名/IP)
openssl req -new -key server_private_DNSError.key -passin pass:123456 -out server_DNSError.csr -subj "/C=CN/ST=beijing/L=beijing/O=huawei/OU=huawei/CN=www.localhost.com"
openssl req -in server_DNSError.csr -noout -text
# 生成服务器证书,用根CA证书签发(csr)
openssl x509 -req -days 365 -in server_DNSError.csr -CA rootCA.crt -CAkey rootCA_private.key -passin pass:123456 -CAcreateserial -out server_DNSError.crt -extfile openssl.cnf -extensions v3_req_server
openssl x509 -in server_DNSError.crt -noout -text
# 私钥+证书合并到一个文件
openssl pkcs12 -export -passout pass:123456 -out server_DNSError.pfx -inkey server_private_DNSError.key -passin pass:123456 -in server_DNSError.crt
# pfx转换为jks命令
keytool -importkeystore -srckeystore server_DNSError.pfx -srcstorepass 123456 -srcstoretype pkcs12 -destkeystore server_DNSError.jks -deststorepass 123456 -deststoretype JKS
# 查看jks文件内容
keytool -list -keystore server_DNSError.jks -storepass 123456 -v

5.3 生成吊销列表

1、配置文件增加内容,重点注意(调整)(新建)标注选项。否则可能命令执行报错 2、将要吊销的证书移动到 crl 文件夹中

####################################################################
[ ca ]
default_ca      = CA_default            # 证书请求

####################################################################
[ CA_default ]

dir             = .              # 保存所有信息的文件夹(调整)
certs           = $dir/certs            # 保存已生成证书的文件夹
crl_dir         = $dir/crl              # 保存吊销证书的文件夹(新建)
database        = $dir/index.txt        # 保存签发证书的文本数据库文件(新建)
#unique_subject = no                    # 同一个subject是否只能创建一个证书,设为no表示可以创
                                        # 建多个
new_certs_dir   = $dir/newcerts         # 保存新签发证书的默认目录,文件后缀是.pem


certificate     = $dir/rootCA.crt       # 保存CA本身根证书的文件名(调整)
serial          = $dir/serial           # 签发证书时使用的序列号文本文件,里面必须包含下一个
                                        # 可用的16进制数字
crlnumber       = $dir/crlnumber        # 存放当前CRL编号的文件(新建,且内容为 00)
                                        # 对于v1版本的CRL则必须注释掉该行
crl             = $dir/crl.pem          # 当前crl文件
private_key     = $dir/rootCA_private.key   # 存放CA自身私钥的文件名(调整)

x509_extensions = usr_cert              # 定义X.509证书扩展项的字段
                                        # 没有提供这个字段则生成X.509v1而不是v3格式的证书。

# 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

# Extension copying option: use with caution.
# copy_extensions = copy

# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
# so this is commented out by default to leave a V1 CRL.
# crlnumber must also be commented out to leave a V1 CRL.
# crl_extensions	= crl_ext

default_days	= 365			# how long to certify for
default_crl_days= 30			# how long before next CRL
default_md	= default		# use public key default MD
preserve	= no			# keep passed DN ordering

# A few difference way of specifying how similar the request should look
# For type CA, the listed attributes must be the same, and the optional
# and supplied fields are just that :-)
policy		= policy_match

# For the CA policy
[ policy_match ]
countryName		= match
stateOrProvinceName	= match
organizationName	= match
organizationalUnitName	= optional
commonName		= supplied
emailAddress		= optional

# For the 'anything' policy
# At this point in time, you must list all acceptable 'object'
# types.
[ policy_anything ]
countryName		= optional
stateOrProvinceName	= optional
localityName		= optional
organizationName	= optional
organizationalUnitName	= optional
commonName		= supplied
emailAddress		= optional

####################################################################

命令行操作

# 1.吊销数字证书
openssl ca -revoke ./crl/server.crt -config openssl.cnf
# 2.更新吊销证书列表
openssl ca -gencrl -out crl.pem -config openssl.cnf
# 3.查看吊销列表
openssl crl -in crl.pem -noout -text

# 问题:更新吊销证书列表。命令执行报错:error while loading CRL number
# 原因:读取 $dir/crlnumber 文件获取吊销证书的吊销序号,文件内容为空,没有 CRL number导致
# 解决方法:$dir/crlnumber 创建文件并内容为 00 。就是保存个序号用来给吊销证书编号

7.证书吊销列表扩展知识

证书吊销列表-百度百科

在X.509标准中采纳的是基于证书吊销列表(Certificate Revocation List,CRL)和基于在线证书状态协议(Online Certificate Status Protocol,OCSP)两种。

CA也可以吊销已经签发的证书,基本的方式包括两类 CRL 文件和 OCSP。

CRL(Certificate Revocation List), 证书吊销列表(什么是证书吊销列表(CRL)?吊销列表起什么作用),一个单独的文件。该文件包含了 CA 已经吊销的证书序列号(唯一)与吊销日期,同时该文件包含生效日期并通知下次更新该文件的时间,当然该文件必然包含 CA 私钥的签名以验证文件的合法性。

OCSP(Online Certificate Status Protocol), 证书状态在线查询协议,一个实时查询证书是否吊销的方式。请求者发送证书的信息并请求查询,服务器返回正常、吊销或未知中的任何一个状态。

OCSP 服务由独立的 OCSP 服务器来提供服务,目前WoSign新证书颁发系统支持 OCSP 方式查询证书状态。

CRL和OCSP区别: CRL 是 不能及时反映证书的实际状态的。而 OCSP 就能满足实时在线查询证书状态的要求。它为电子商务网站提供了一种实时检验数字证书有效性的途径,比下载和处理 CRL 的传统方式更快、更方便和更具独立性。请求者发送查询请求, OCSP 服务器会返回证书可能的三个状态:正常、吊销和未知。

CA是证书颁发机构,由CA机构颁发的证书都可以成为CA证书,SSL证书只是CA机构颁发证书的其中一种,用于HTTPS加密协议