OpenSSL使用

最后更新:2020-06-20

一直对OpenSSL生成证书这一块似懂非懂,每次要做证书都是找一大堆资料才搞定。

1. 证书签署请求(CSR)

如果你想从 证书颁发机构(certificate authority)(CA)那里获得 SSL 证书,你必须生成一个 证书签署请求(certificate signing request)(CSR)。一个 CSR 主要是由一个密钥对的公钥和一些附加信息组成。当证书被签署时,这两部分都会被插入到证书中。

每当你生成一个 CSR 时,你会被提示提供有关证书的信息。这些信息被称为 区分名称(Distinguised Name)(DN)。DN 中的一个重要字段是 通用名称(Common Name)(CN),它应该是你打算使用证书的主机的 完全合格域名(Fully Qualified Domain Name)(FQDN)。当创建 CSR 时,也可以通过命令行或文件传递信息来跳过交互式提示。

DN 中的其他项目提供了有关你的业务或组织的附加信息。如果你是从证书机构购买 SSL 证书,通常要求这些附加字段(如“ 组织(Organization)”)准确地反映你的组织的详细信息。

下面是一个 CSR 信息提示的例子:

---
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:New York
Locality Name (eg, city) []:Brooklyn
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example Brooklyn Company
Organizational Unit Name (eg, section) []:Technology Division
Common Name (e.g. server FQDN or YOUR name) []:examplebrooklyn.com
Email Address []:

如果你想非交互式地回答 CSR 信息提示,你可以通过在任何请求 CSR 信息的 OpenSSL 命令中添加 -subj 选项来实现。这里是该选项的一个例子,使用上面代码块中显示的相同信息:

-subj "/C=US/ST=New York/L=Brooklyn/O=Example Brooklyn Company/CN=examplebrooklyn.com"

1.1. 生成一个私钥和一个 CSR

如果你想使用 HTTPS(HTTP over TLS)来保护你的 Apache HTTP 或 Nginx Web 服务器的安全,并且你想使用一个证书颁发机构(CA)来颁发 SSL 证书,那么就使用这个方法。生成的 CSR 可以发送给 CA,请求签发由 CA 签名的 SSL 证书。如果你的 CA 支持 SHA-2,请添加 -sha256 选项,用 SHA-2 签署 CSR。

这条命令从头开始创建一个 2048 位的私钥(domain.key)和一个 CSR(domain.csr):

openssl req \
       -newkey rsa:2048 -nodes -keyout domain.key \
       -out domain.csr

选项 -newkey rsa:2048 指定密钥应该是 2048 位,使用 RSA 算法生成。选项 -nodes 指定私钥没有用密码加密。这里没有包含 -new 选项,而是隐含在其中,表示正在生成一个 CSR。

1.2. 从现有的私钥中生成一个 CSR

如果你已经有了私钥,并想用它向 CA 申请证书,请使用这个方法。

该命令基于现有的私钥(domain.key)创建一个新的 CSR(domain.csr):

openssl req \
       -key domain.key \
       -new -out domain.csr

选项 -key 指定一个现有的私钥(domain.key),它将被用来生成一个新的 CSR。选项 -new 表示正在生成一个 CSR。

1.3. 从现有的证书和私钥生成 CSR

如果你想更新现有的证书,但由于某些原因,你或你的 CA 没有原始的 CSR,请使用这个方法。基本上可以省去重新输入 CSR 信息的麻烦,因为它是从现有证书中提取信息的。

该命令基于现有的证书(domain.crt)和私钥(domain.key)创建一个新的 CSR(domain.csr):

openssl x509 \
       -in domain.crt \
       -signkey domain.key \
       -x509toreq -out domain.csr

选项 -x509toreq 指定你使用一个 X509 证书来制作 CSR。

2. SSL 证书

如果你想使用 SSL 证书来确保服务的安全,但你不需要 CA 签名的证书,一个有效的(和免费的)解决方案是签署你自己的证书。

你可以自己签发的一种常见证书是 自签证书(self-signed certificate)。自签证书是用自己的私钥签署的证书。自签证书和 CA 签名证书一样可以用来加密数据,但是你的用户会显示一个警告,说这个证书不被他们的计算机或浏览器信任。因此,只有当你不需要向用户证明你的服务身份时,才可以使用自签名证书(例如非生产或非公开服务器)。

2.1. 生成自签证书

如果你想使用 HTTPS(HTTP over TLS)来保护你的 Apache HTTP 或 Nginx Web 服务器,并且你不需要你的证书由 CA 签名,那么就使用这个方法。

这个命令可以从头开始创建一个 2048 位的私钥(domain.key)和一个自签证书(domain.crt):

openssl req \
       -newkey rsa:2048 -nodes -keyout domain.key \
       -x509 -days 365 -out domain.crt

选项 -x509 告诉 req 子命令创建一个自签名的证书。-days 365 选项指定证书的有效期为 365 天。它会生成一个临时的 CSR,以收集与证书相关的信息。

2.2. 现有私钥生成自签名证书

如果你已经有了一个私钥,并且你想用它来生成一个自签证书,请使用这个方法。

这条命令可以从现有的私钥(domain.key)中创建一个自签证书(domain.crt):

openssl req \
       -key domain.key \
       -new \
       -x509 -days 365 -out domain.crt

选项 -x509 告诉 req 子命令创建一个自签证书。-days 365 选项指定证书的有效期为 365 天。选项 -new 启用 CSR 信息提问。

2.3. 从现有的私钥和 CSR 生成自签证书

如果你已经有了私钥和 CSR,并且你想用它们生成一个自签证书,请使用这个方法。

这条命令将从现有的私钥(domain.key)和(domain.csr)中创建一个自签证书(domain.crt)。

openssl x509 \
       -signkey domain.key \
       -in domain.csr \
       -req -days 365 -out domain.crt

选项 -days 365 指定证书的有效期为 365 天。

2.1. 查看证书

证书和 CSR 文件是以 PEM 格式编码的,不适合被人读取。

2.1.1. 查看 CSR 条目

该命令允许你查看和验证纯文本的 CSR(domain.csr)的内容:

openssl req \
       -text -noout -verify \
       -in domain.csr

2.1.2. 查看证书条目

该命令允许你查看纯文本证书(domain.crt)的内容:

openssl x509 \
       -text -noout \
       -in domain.crt

2.1.3. 验证证书由 CA 签署

使用此命令验证证书(domain.crt)是否由特定的 CA 证书(ca.crt)签署:

openssl verify \
       -verbose -CAFile ca.crt \
       domain.crt

3. 私钥

3.1. 创建私钥

使用该命令创建一个受密码保护的 2048 位私钥(domain.key):

openssl genrsa \
       -des3 -out domain.key 2048

在提示时输入密码以完成该过程。

3.2. 验证私钥

使用此命令检查私钥(domain.key)是否为有效密钥:

openssl rsa \
       -check -in domain.key

如果你的私钥已经加密,系统会提示你输入它的密码,成功后,未加密的密钥会在终端上输出。

3.3. 验证私钥是否与证书和 CSR 匹配

使用这些命令来验证私钥(domain.key)是否匹配证书(domain.crt)和 CSR(domain.csr):

openssl rsa  -noout -modulus -in domain.key | openssl md5
openssl x509 -noout -modulus -in domain.crt | openssl md5
openssl req  -noout -modulus -in domain.csr | openssl md5

如果每条命令的输出都是相同的,那么私钥、证书和 CSR 就极有可能是相关的。

3.4. 加密私钥

这需要一个未加密的私钥(unencrypted.key),并输出它的加密版本(encrypted.key):

openssl rsa -des3 \
       -in unencrypted.key \
       -out encrypted.key

输入你所需的密码,以加密私钥。

3.5. 解密私钥

这需要一个加密的私钥(encrypted.key),并输出一个解密的版本(decrypted.key):

openssl rsa \
       -in encrypted.key \
       -out decrypted.key

在提示时,输入加密密钥的密码。

4. 转换证书格式

我们一直在使用的所有证书都是 ASCII 码 PEM 编码的 X.509 证书。还有很多其他的证书编码和容器类型;一些应用程序喜欢某些格式而不是其他格式。此外,这些格式中的许多格式可以在一个文件中包含多个项目,如私钥、证书和 CA 证书。

OpenSSL 可以用来将证书在这些格式间转换。

4.1. 将 PEM 转换为 DER

如果要将 PEM 编码的证书(domain.crt)转换为 DER 编码的证书(domain.der),即二进制格式,请使用此命令:

openssl x509 \
       -in domain.crt \
       -outform der -out domain.der

DER 格式通常与 Java 一起使用。

4.2. 将 DER 转换为 PEM

如果要将 DER 编码的证书(domain.der)转换为 PEM 编码的证书(domain.crt),请使用此命令:

openssl x509 \
       -inform der -in domain.der \
       -out domain.crt

4.3. 将 PEM 转换为 PKCS7

如果你想把 PEM 证书(domain.crt 和 ca-chain.crt)添加到 PKCS7 文件(domain.p7b)中,请使用该命令:

openssl crl2pkcs7 -nocrl \
       -certfile domain.crt \
       -certfile ca-chain.crt \
       -out domain.p7b

请注意,你可以使用一个或多个 -certfile 选项来指定要添加到 PKCS7 文件中的证书。

PKCS7 文件,也被称为 P7B,通常用于 Java Keystores 和 Microsoft IIS(Windows)。它们是 ASCII 文件,可以包含证书和 CA 证书。

4.4. 将 PKCS7 转换为 PEM

如果你想将 PKCS7 文件(domain.p7b)转换为 PEM 文件,请使用该命令:

openssl pkcs7 \
       -in domain.p7b \
       -print_certs -out domain.crt

请注意,如果你的 PKCS7 文件中有多个项目(如证书和 CA 中间证书),创建的 PEM 文件将包含其中的所有项目。

4.5. 将 PEM 转换为 PKCS12

如果你想使用私钥(domain.key)和证书(domain.crt),并将它们组合成一个 PKCS12 文件(domain.pfx),请使用这个命令:

openssl pkcs12 \
       -inkey domain.key \
       -in domain.crt \
       -export -out domain.pfx

系统会提示你输入导出密码,你可以留空。请注意,在这种情况下,你可以通过将多个证书连接到一个 PEM 文件(domain.crt)中来添加一个证书链到 PKCS12 文件中。

PKCS12 文件,也被称为 PFX 文件,通常用于在 Micrsoft IIS(Windows)中导入和导出证书链。

4.6. 将 PKCS12 转换为 PEM

如果你想转换 PKCS12 文件(domain.pfx)并将其转换为 PEM 格式(domain.combined.crt),请使用此命令:

openssl pkcs12 \
       -in domain.pfx \
       -nodes -out domain.combined.crt

请注意,如果你的 PKCS12 文件中有多个项目(如证书和私钥),创建的 PEM 文件将包含其中的所有项目。

5. X509证书链

x509证书一般会用到三类文件,key,csr,crt。

  • key是私用密钥,openssl格式,通常是rsa算法。
  • csr是证书请求文件,用于申请证书。在制作csr文件的时候,必须使用自己的私钥来签署申请,还可以设定一个密钥。
  • crt是CA认证后的证书文件(windows下面的csr,其实是crt),签署人用自己的key给你签署的凭证。

6. openssl文件说明

  • .key格式:私有的密钥,与证书一一配对
  • .csr格式:证书签名请求(证书请求文件),含有公钥信息,certificate signing request的缩写
  • .crt格式:证书文件,certificate的缩写,可以是二进制格式(der),可以是文本格式(pem)。只包含证书,不保存私钥
  • .crl格式:证书吊销列表,Certificate Revocation List的缩写
  • .pem格式:用于导出,导入证书时候的证书的格式,有证书开头,结尾的格式
  • .pkcs12 .pfx .p12 二进制格式,同时包含证书和私钥(通过.crt或者.cer与私钥.key合成),一般有密码保护。

7. OpenSSL命令

  • -aes256 使用AES算法(256为密钥)对产生的私钥加密。可选算法包括DES,DESede,IDEA和AES。
  • -key 密钥
  • -new 表示新的请求。
  • -out 输出路径
  • -subj 指定用户信息
  • ca 签发证书命令
  • genrsa 产生RSA密钥命令
  • pkcs12 PKCS#12编码格式证书命令。
  • rand 随机数命令
  • req 产生证书签发申请命令
  • x509 签发X.509格式证书命令。
  • -CAcreateserial 表示创建CA证书序列号
  • -CAkey 表示CA证书密钥
  • -CAserial 表示CA证书序列号文件
  • -CA 表示CA证书
  • -cert 表示证书文件
  • -clcerts 表示仅导出客户证书。
  • -days 表示有效天数
  • -export 表示导出证书。
  • -extensions 表示按OpenSSL配置文件v3_ca项添加扩展。
  • -extensions 表示按OpenSSL配置文件v3_req项添加扩展。
  • -inkey 表示输入文件
  • -in 表示输入文件
  • -keyfile 表示根证书密钥文件
  • -req 表示证书输入请求。
  • -sha1 表示证书摘要算法,这里为SHA1算法。
  • -signkey 表示自签名密钥

8. CA根证书生成步骤

生成CA私钥(.key)–>生成CA证书请求(.csr)–>自签名得到CA根证书(.crt)(CA给自已颁发的证书)。

8.1. 生成CA私钥(.key)

openssl genrsa -aes256 -out ca.key 2048
  • genrsa 产生rsa密钥命令。
  • -aes256 使用AES算法(256位密钥)对产生的私钥加密。
  • -out 输出路径。
  • 2048 密钥的长度位数(默认长度为512位)。

示例

openssl genrsa -aes256 -out ca.key 2048
Generating RSA private key, 2048 bit long modulus
.......+++
....+++
e is 65537 (0x10001)
Enter pass phrase for ca.key:
Verifying - Enter pass phrase for ca.key:

8.2. 生成CA证书请求(.csr)(内含公钥)

openssl req -new -key ca.key -out ca.csr -subj "/C=CN/ST=BJ/L=BJ/O=ZLEX/OU=zlex/CN=*.ZLEX.ORG"
  • req 产生证书签发申请命令。
  • -new 新请求
  • -key 密钥,ca.key文件
  • -out 输出路径
  • -subj 指定用户信息,这里使用泛域名”*.zlex.org”作为用户名。

得到根证书生签发申请之后,可以将其发送给CA机构签发,也可以自行签发根证书。

自定义区域

  • Country Name (2 letter code) [XX]:CN 证书持有者所在国家
  • State or Province Name (full name) []:BJ 证书持有者所在州或省份(可省略不填)
  • Locality Name (eg, city) []:BJ 证书持有者所在城市(可省略不填)
  • Organization Name (eg, company) []:NH 证书持有者所属组织或公司
  • Organizational Unit Name (eg, section) []: 证书持有者所属部门(可省略不填)
  • Common Name (eg, your name or your server’s hostname) []: 域名
  • Email Address []: 邮箱(可省略不填)
  • challenge password: 自定义密码
  • An optional company name: 可选公司名称

示例

openssl req -new -key ca.key -out ca.csr
Enter pass phrase for ca.key:
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]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:localhost
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:123456
An optional company name []:

8.3. 自签名得到CA根证书(.crt)

openssl x509 -req -days 10000 -sha1 -extensions v3_ca -signkey ca.key -in ca.csr -out ca.crt
  • x509 签发X.509格式证书命令
  • -req 表示证书输入。
  • days 表示有效。
  • -sha1 表示证书摘要算法,这里为SHA1。
  • -extensions 表示按openssl配置文件v3_ca项添加。
  • -signkey 表示自签名。
  • -in 表示输入文件。
  • -out 表示输出文件。

示例

openssl x509 -req -days 10000 -sha1 -extensions v3_ca -signkey ca.key -in ca.csr -out ca.crt
Signature ok
subject=/C=Cn/ST=Some-State/O=Internet Widgits Pty Ltd/CN=localhost
Getting Private key
Enter pass phrase for ca.key:

得到三个文件

ca.crt  ca.csr  ca.key

9. 用户证书生成步骤

一般说的生成用户证书分两种,客户端证书和服务端证书,除了名称不一样步骤命令完全一样一样的。

生成私钥(.key)–>生成证书请求(.csr)–>用CA根证书签名得到证书(.crt)

9.1. 生成私钥

openssl genrsa -aes256 -out server.key 2048

示例

openssl genrsa -aes256 -out server.key 2048
Generating RSA private key, 2048 bit long modulus
.................................................................................................+++
..........................................................................................................+++
e is 65537 (0x10001)
Enter pass phrase for server.key:
Verifying - Enter pass phrase for server.key:

9.2. 生成证书请求文件

openssl req -new -key server.key -out server.csr -subj "/C=CN/ST=BJ/L=BJ/0=zlex/OU=zlex/CN=www.zlex.org"

示例

openssl req -new -key server.key -out server.csr
Enter pass phrase for server.key:
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]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:localhost
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:123456
An optional company name []:

9.3. 使用 CA 证书及CA密钥 对请求签发证书进行签发,生成 x509证书

openssl x509 -req -days 3650 -sha1 -extensions v3_req  -CA  ca.crt -CAkey ca.key  -CAserial ca.srl  -CAcreateserial -in server.csr -out server.cer

示例

openssl x509 -req -days 3650 -sha1 -extensions v3_req  -CA  ca.crt -CAkey ca.key  -set_serial 01  -in server.csr -out server.crt
Signature ok
subject=/C=CN/ST=Some-State/O=Internet Widgits Pty Ltd/CN=localhost
Getting CA Private Key
Enter pass phrase for ca.key:

对于Java程序来说,还要将证书转换成支持的格式

openssl pkcs8 -topk8 -nocrypt -in server.key -out server.pem

客户端证书与服务端基本类似不在描述

10. 配置

OpenSSL配置文件在/etc/pki/tls/openssl.cnf文件中,其配置文件最主要的就是CA的一些配置

default_ca = CA_default:默认CA配置选项就是CA_default

dir = /etc/pki/CA CA数据存储目录

certs = $dir/certs 签发过的证书存储目录

crl_dir = $dir/crl 证书吊销列表放置路径

database = $dir/index.txt 证书的索引文件,这里存储的是签发的证书的索引

unique_subject = no 证书的主体信息是否唯一

new_certs_dir = $dir/newcerts 刚刚签署完成的证书放在哪里

certificate = $dir/cacert.pem CA自己的证书放在哪里

serial = $dir/serial 证书序列号

crlnumber = $dir/crlnumber 被吊销的证书序列号

crl = $dir/crl.pem 被吊销的证书

private_key = $dir/private/cakey.pem CA自己的私钥放置位置

11. 查看证书细节

打印证书的过期时间

openssl x509 -in signed.crt -noout -dates

打印出证书的内容:

openssl x509 -in cert.pem -noout -text

打印出证书的系列号

openssl x509 -in cert.pem -noout -serial

打印出证书的拥有者名字

openssl x509 -in cert.pem -noout -subject

以RFC2253规定的格式打印出证书的拥有者名字

openssl x509 -in cert.pem -noout -subject -nameopt RFC2253

在支持UTF8的终端一行过打印出证书的拥有者名字

openssl x509 -in cert.pem -noout -subject -nameopt oneline -nameopt -escmsb

打印出证书的MD5特征参数

openssl x509 -in cert.pem -noout -fingerprint

打印出证书的SHA特征参数

openssl x509 -sha1 -in cert.pem -noout -fingerprint

把PEM格式的证书转化成DER格式

openssl x509 -in cert.pem -inform PEM -out cert.der -outform DER

把一个证书转化成CSR

openssl x509 -x509toreq -in cert.pem -out req.pem -signkey key.pem

给一个CSR进行处理,颁发字签名证书,增加CA扩展项

openssl x509 -req -in careq.pem -extfile openssl.cnf -extensions v3_ca -signkey key.pem -out cacert.pem

给一个CSR签名,增加用户证书扩展项

openssl x509 -req -in req.pem -extfile openssl.cnf -extensions v3_usr -CA cacert.pem -CAkey key.pem -CAcreateserial

查看csr文件细节:

openssl req -in my.csr -noout -text

12. 使用openssl生成多DNS的自签名证书

修改openssl.cnf

确保[ req ]下存在以下2行(默认第一行是有的,第2行被注释了)

[ req ]
distinguished_name = req_distinguished_name
req_extensions = v3_req

[ v3_req ]段最后一行后新增内容 subjectAltName = @alt_names(前2行默认存在)

[ v3_req ]

# Extensions to add to a certificate request

basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment

以下新增内容

subjectAltName = @alt_names

[ alt_names ]
DNS.1 = *.domain1.com
DNS.2 = *.domain2.com
DNS.3 = *.domain2.com

在生成签发请求和证书的时候加上 -config **/openssl.cnf,不同命令的参数可能不同

如果openssl的版本是1.1.1+,可以使用-add-ext参数增加扩展熟悉

13. 测试证书

Openssl提供了简单的client和server工具,可以用来模拟SSL连接,做测试使用。

连接到远程服务器

openssl s_client -connect www.google.com.hk:443

模拟的HTTPS服务,可以返回Openssl相关信息

openssl s_server -accept 443 -cert myserver.crt -key myserver.key -www
  • -accept 用来指定监听的端口号
  • -cert -key 用来指定提供服务的key和证书

用的较少,知道有这个就行了

测试单向认证

openssl s_server -accept 10001 -key server.key -cert server.crt
openssl s_client -connect localhost:10001
openssl s_client -connect localhost:10001 -CAfile ca.key

测试双向认证

openssl s_server -accept 10001 -key server.key -cert server.crt -Verify 5
openssl s_client -connect localhost:10001
openssl s_client -connect localhost:10001 -cert client.crt -key client.key

14. 参考资料

https://blog.csdn.net/sunhuansheng/java/article/details/82902185

https://zhuanlan.zhihu.com/p/146587866

Edgar

Edgar
一个略懂Java的小菜比