如何创建和签署 SSL/TLS 证书
在上一篇文章中,我们讨论了数字证书如何帮助身份验证并在 TLS 中提供安全可靠的密钥交换过程。
今天我们将详细学习如何生成证书并由证书颁发机构 (CA) 签署。
在本教程中,我们不会将证书签名请求 (CSR) 提交给真正的 CA。相反,我们将同时扮演两个角色:证书颁发机构 (CA) 和证书申请人。
因此,我们要做的如下:
- 第一步,我们将为 CA 生成私钥及其自签名证书。它们稍后将用于签署 CSR。
- 第二步,我们将为想要使用 TLS 的 Web 服务器生成私钥及其配对的 CSR。
- 最后,我们将使用 CA 的私钥来签署 Web 服务器的 CSR 并取回签署的证书。
为了完成所有这些操作,我们需要openssl
安装。如果你使用的是 Mac,它可能已经安装好了。你可以运行以下命令来查看它正在运行的版本:
openssl version
就我而言,它是LibreSSL版本 2.8.3。
我们可以通过此链接访问其手册文档。
1.生成CA的私钥和证书
我们要使用的第一个命令是openssl req,它代表请求。此命令用于创建和处理证书签名请求。它也可以用于为 CA 创建自签名证书,这正是我们第一步想要的。
openssl req -x509 -newkey rsa:4096 -days 365 -keyout ca-key.pem -out ca-cert.pem
该-x509
选项用于告诉 openssl 输出自签名证书而不是证书请求。如果您不知道,X509只是公钥证书的标准格式。
该-newkey rsa:4096
选项的作用是告诉 openssl 同时创建一个新的 RSA 私钥(4096 位)及其证书请求。由于我们同时使用此-x509
选项,因此它将输出证书而不是证书请求。
下一个选项是-days 365
,它指定证书有效的天数。
然后我们使用-keyout
选项告诉 openssl 将创建的私钥写入ca-key.pem
文件
最后,-out
选择将证书写入ca-cert.pem
文件。
当我们运行此命令时,openssl 将开始生成私钥。
一旦生成密钥,我们将被要求提供一个密码,该密码将用于在将私钥写入 PEM 文件之前对其进行加密。
为什么要加密?因为如果私钥文件被黑客入侵,黑客在不知道密码的情况下无法使用它做任何事情。
接下来,openssl会要求我们提供一些身份信息来生成证书:
- 国家代码
- 州或省名称
- 组织名称
- 单位名称
- 通用名称(或域名)
- 电子邮件地址
就这样!证书和私钥文件将成功生成。
如果我们检查私钥文件ca-key.pem
,我们可以看到它显示ENCRYPTED PRIVATE KEY
:
-----BEGIN ENCRYPTED PRIVATE KEY-----
MIIJnzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQILfki090rvloCAggA
MB0GCWCGSAFlAwQBKg...GNYc7i9SVDBoA==
-----END ENCRYPTED PRIVATE KEY-----
ca-cert.pem
另一方面,证书未加密,而仅经过 base64 编码,因为它仅包含公钥、身份信息和每个人都可以看到的签名。
-----BEGIN CERTIFICATE-----
MIIFxjCCA64CCQCNT+eP2vjJxzANBgkqhkiG9w0BAQsFADCBpDELMAkGA1UEBhMC
RlIxEjAQBgNVBAgMC...udJwE7HnnA7lpA
-----END CERTIFICATE-----
我们可以使用openssl x509命令显示此证书中编码的所有信息。此命令也可用于签署证书请求,我们稍后会看到。
openssl x509 -in ca-cert.pem -noout -text
这里我们使用-in
选项传入 CA 的证书文件。并使用-noout
选项告诉它不要输出原始的 base64 编码值。我们之所以使用-text
选项,是因为我们想以可读的文本格式显示它。
现在我们可以看到证书的所有信息,例如版本号、序列号。由于这是一个自签名证书,因此颁发者和主体是相同的。然后是 RSA 公钥和签名。
我要复制此命令并将其保存到gen.sh
脚本中。我希望通过此脚本自动执行生成一组密钥和证书的过程。
在进入第二步之前,我将向您展示另一种提供身份信息的方法,而无需像以前那样以交互方式输入。为此,我们必须在命令-subj
中添加 (subject) 选项openssl req
:
openssl req -x509 -newkey rsa:4096 -days 365 -keyout ca-key.pem -out ca-cert.pem -subj "/C=FR/ST=Occitanie/L=Toulouse/O=Tech School/OU=Education/CN=*.techschool.guru/emailAddress=techschool.guru@gmail.com"
在此主题字符串中:
/C=FR
代表国家/ST=Occitanie
适用于州或省/L=Toulouse
代表地名或城市/O=Tech School
适用于组织/OU=Education
适用于组织单位/CN=*.techschool.guru
是通用名称或域名/emailAddress=techschool.guru@gmail.com
用于电子邮件地址
现在让我们rm *.pem
在脚本顶部添加命令(删除所有 pem 文件)gen.sh
,并在终端中运行它。
rm *.pem
# 1. Generate CA's private key and self-signed certificate
openssl req -x509 -newkey rsa:4096 -days 365 -keyout ca-key.pem -out ca-cert.pem -subj "/C=FR/ST=Occitanie/L=Toulouse/O=Tech School/OU=Education/CN=*.techschool.guru/emailAddress=techschool.guru@gmail.com"
echo "CA's self-signed certificate"
openssl x509 -in ca-cert.pem -noout -text
# 2. Generate web server's private key and certificate signing request (CSR)
# 3. Use CA's private key to sign web server's CSR and get back the signed certificate
我们仍然被提示输入密码,但它不再要求身份信息,因为我们已经在主题选项中提供了这些信息。
2. 生成 Web 服务器的私钥和 CSR
现在下一步是为我们的 Web 服务器生成私钥和 CSR。
它与我们在第一步中使用的命令几乎相同。不同之处在于,这次我们不想进行自签名,因此应该删除该-x509
选项。-days
由于我们不创建证书,而只是创建 CSR,因此该选项也应该删除。
openssl req -newkey rsa:4096 -keyout server-key.pem -out server-req.pem -subj "/C=FR/ST=Ile de France/L=Paris/O=PC Book/OU=Computer/CN=*.pcbook.com/emailAddress=pcbook@gmail.com"
输出密钥的名称应为server-key.pem
。输出证书请求文件应为server-req.pem
。主题应包含我们的 Web 服务器信息。
现在,当我们运行此命令时,将生成加密的私钥和证书签名请求文件。
这次,server-req.pem
文件中显示的是CERTIFICATE REQUEST
,而不是文件CERTIFICATE
中的ca-cert.pem
。这是因为它不是像之前那样的证书,而是证书签名请求。
-----BEGIN CERTIFICATE REQUEST-----
MIIE2DCCAsACAQAwgZIxCzAJBgNVBAYTAkZSMRYwFAYDVQQIDA1JbGUgZGUgRnJh
bmNlMQ4wDAYDVQQHDAVQ...pWofr2eOeBQ4Q=
-----END CERTIFICATE REQUEST-----
现在让我们进入第 3 步并签署此请求。
3. 签署 Web 服务器的证书请求
要签署证书,我们将使用之前显示证书时使用的openssl x509命令。让我们打开终端并运行以下命令:
openssl x509 -req -in server-req.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem
在这个命令中,我们使用-req
选项告诉 openssl 我们将传入一个证书请求。我们使用-in
选项,后跟请求文件的名称:server-req.pem
。
接下来我们使用-CA
选项传入CA的证书文件:ca-cert.pem
。并-CAkey
使用选项传入CA的私钥:ca-key.pem
。
然后,一个重要的选项是-CAcreateserial
。基本上,CA 必须确保其签名的每个证书都具有唯一的序列号。因此,使用此选项时,如果不存在下一个序列号,则会生成一个包含该文件的文件。
最后,我们使用-out
选项来指定要将输出证书写入的文件。
现在正如您所见,由于 CA 的私钥已加密,因此 openssl 要求输入密码才能解密,然后才能使用它来签名证书。这是针对 CA 私钥被黑客入侵的应对措施。
好的,现在我们已经获得了 Web 服务器的签名证书。让我们将其以纯文本格式打印出来。
这是它唯一的序列号0xb141e873fd7b8567
。我们还可以看到一个ca-cert.srl
文件,里面也包含相同的序列号。
B141E873FD7B8567
默认情况下,证书有效期为30天。我们可以通过-days
在签名命令中添加选项来更改它。
openssl x509 -req -in server-req.pem -days 60 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem
现在有效期已更改为60天。
一个证书可以用于多个域名不同的网站。我们可以通过在签署证书请求时指定“主体备用名称”扩展名来实现这一点。
-extfile
该命令的选项允许我们指定包含扩展名的文件。我们可以在此页面openssl x509
中看到配置文件的格式。
我们可以使用多种名称作为替代名称,例如email
、DNS
或IP
。我将创建一个server-ext.cnf
包含以下内容的新文件:
subjectAltName=DNS:*.pcbook.com,DNS:*.pcbook.org,IP:0.0.0.0
这里我设置DNS
了多个域名:*.pcbook.com
和*.pcbook.org
。我还设置了在本地主机上开发时将使用的域名IP
。0.0.0.0
现在在证书签名命令中,让我们添加-extfile
选项并传入扩展配置文件的名称:
openssl x509 -req -in server-req.pem -days 60 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile server-ext.cnf
现在,结果证书文件有一个新的扩展部分,其中包含我们选择的所有主题备用名称:
Certificate:
...
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=FR, ST=Occitanie, L=Toulouse, O=Tech School, OU=Education, CN=*.techschool.guru/emailAddress=techschool.guru@gmail.com
Validity
Not Before: Apr 10 18:17:05 2020 GMT
Not After : Jun 9 18:17:05 2020 GMT
Subject: C=FR, ST=Ile de France, L=Paris, O=PC Book, OU=Computer, CN=*.pcbook.com/emailAddress=pcbook@gmail.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
Modulus:
00:cb:e2:2b:c3:68:...
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:*.pcbook.com, DNS:*.pcbook.org, IP Address:0.0.0.0
Signature Algorithm: sha1WithRSAEncryption
5e:67:4d:f7:91:89:fc:...
因此看起来我们的自动化脚本已经准备好了,除了我们必须输入大量密码来保护私钥。
如果我们只是想将其用于开发和测试,我们可以告诉 openssl 不要加密私钥,这样它就不会要求我们输入密码。
我们通过-nodes
向openssl req
命令添加选项来实现这一点,如下所示:
rm *.pem
# 1. Generate CA's private key and self-signed certificate
openssl req -x509 -newkey rsa:4096 -days 365 -nodes -keyout ca-key.pem -out ca-cert.pem -subj "/C=FR/ST=Occitanie/L=Toulouse/O=Tech School/OU=Education/CN=*.techschool.guru/emailAddress=techschool.guru@gmail.com"
echo "CA's self-signed certificate"
openssl x509 -in ca-cert.pem -noout -text
# 2. Generate web server's private key and certificate signing request (CSR)
openssl req -newkey rsa:4096 -nodes -keyout server-key.pem -out server-req.pem -subj "/C=FR/ST=Ile de France/L=Paris/O=PC Book/OU=Computer/CN=*.pcbook.com/emailAddress=pcbook@gmail.com"
# 3. Use CA's private key to sign web server's CSR and get back the signed certificate
openssl x509 -req -in server-req.pem -days 60 -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile server-ext.cnf
echo "Server's signed certificate"
openssl x509 -in server-cert.pem -noout -text
现在,如果我们再次运行gen.sh
,它将不再要求输入密码。如果我们查看私钥文件,它将是PRIVATE KEY
,而不是ENCRYPTED PRIVATE KEY
像以前那样。
-----BEGIN PRIVATE KEY-----
MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDL4ivDaIzDM3my
VDzT2Mw5R9bicXS...AxAt2Ldmc4=
-----END PRIVATE KEY-----
4.验证证书
在结束之前,还有最后一件事,我将向您展示如何验证证书是否有效。我们可以使用openssl verify命令来执行此操作:
openssl verify -CAfile ca-cert.pem server-cert.pem
我们只需传入受信任的 CA 证书和我们要验证的证书即可。如果返回结果,OK
则表示证书有效。
今天的文章就到这里。希望对你有用。感谢阅读,我们下期再见!
如果您喜欢这篇文章,请订阅我们的 Youtube 频道并在 Twitter 上关注我们,以便将来获取更多教程。
如果你想加入我目前在 Voodoo 的优秀团队,请查看我们的职位空缺。你可以远程办公,也可以在巴黎/阿姆斯特丹/伦敦/柏林/巴塞罗那现场办公,但需获得签证担保。
文章来源:https://dev.to/techschoolguru/how-to-create-sign-ssl-tls-certificates-2aai