理论上,获得证书很容易。系统管理员或自动化流程生成证书签名请求(Certificate Signing Request —— CSR)。CSR包含CA验证的所有信息,甚至可能更多。您可以将CSR视为未签名的证书,尽管这并不完全正确。无论你如何获得证书,你都会创建CSR。当事情出错时,你需要有能力仔细检查它们。RFC 2986记录了CSR。
目前商业CA提供的一年时间,是忘记你所知道的关于生成CSR的一切的完美时间。如果入侵者窃取了您的私钥,您必须立即生成新的CSR和私钥。记录CSR创建过程和您需要的任何配置文件,以便您可以根据需要轻松重复。编写一个脚本,或者更好的是,完全自动化请求过程。
如果您使用的是ACME,您将配置一次证书签名请求,然后让自动化处理它们。这意味着你会忽略它们,直到发生灾难性的事情,此时你将不得不重新学习CSR。
大多数系统管理员主要在购买商业证书时处理CSR。我们将从这个角度来看待CSR,但所有内容都适用于ACME证书签名请求。
第六章:证书签名请求和商业CA重新用CSR为何投奔商业版?收集信息公钥算法通用名OpenSSL 配置文件创建 CSRs创建 ECDSA CSRsreq主段密码管理req_distinguished_name扩展椭圆曲线参数文件申请ECDSA证书生成RSA CSRsRSA CSR 配置文件请求RSA证书客户端CSRs无主题证书没有配置文件的CSRs查看 CSRs使用 CSR和证书重新连接文件和查找重用密钥
虽然您可以重用CSR来续订证书,但这是一种糟糕的做法。每个CSR都绑定到一个公钥对。虽然你不能证明否定(negative),但“证明你的私钥没有被盗”尤其困难。入侵者更喜欢人们重用私钥。它允许他们使用你的新证书和他们去年偷来的密钥来伪装成你的系统。即使您的密钥从未被盗,经过几次重复使用后,该密钥也会比建议的弱。
每当您续订证书时,都可以使用该密钥创建新的私钥和新的CSR。生成新的私钥是快速、廉价和简单的。它甚至是CSR生成命令的一部分。
许多教程建议重复使用私钥,但这就像在不系安全带的情况下超速行驶,这样你就可以更容易地从后座上拿一罐新鲜的啤酒。你会逃脱惩罚的,也许会持续很长一段时间,但它最终会伤害你。
几十年来,获得X.509证书的唯一方法是从商业证书颁发机构购买一个。如今,DV证书可以免费使用。如果你可以通过ACME获得免费证书,为什么要使用商业CA?
一些组织需要高验证级别(第3章),但大多数免费且廉价的CA只提供域验证(domain validated —— DV)证书。监管、法律或军事标准可能要求您的组织使用OV甚至EV证书。许多专门从事货币的组织在制度上不信任免费服务。如果你的组织的领导人宣布“你必须使用商业证书颁发机构”,甚至“你必须用这个特定的CA”,那么无论你对此事的衷心和技术上的合理意见如何,都会做出这个决定。
如果您想要特殊用途的证书,例如用于运行自己的CA,您也可以使用商业CA。我们将在第10章中讨论这些。
使用商业证书颁发机构时,一定要为替换证书分配资金,以防必须吊销证书。一些CA为吊销提供保险。购买它,并在任何时候使用它,即使你对入侵有一丝怀疑。
CSR是处理商业证书颁发机构的关键。证书签名请求包含CA将验证的所有信息。对于域验证(DV)请求,这可能只是将使用证书的服务器的域名。OV和EV证书需要更多的信息,而且都必须是正确的。
我们将讨论收集信息的一些注意事项、证书的公钥算法以及如何请求和接收证书。
超过域验证的证书需要更多信息。帮自己一个忙,在运行任何命令之前收集所有信息。证书颁发机构相当有能力拒绝与官方文件不匹配的证书签名请求。
X.509中显示为 C 的 country name 使用ISO 3166中定义的两个字母的国家代码。如果您不确定您所在国家的ISO代码,请在提交证书之前进行检查。
ST X.509代码代表您的州(state)或省(province)。不要缩写你所在州的名字。把它拼出来。
Locality ,或 L ,是一种说“city”的花哨方式。你的组织真正位于哪个城市?也许每个人都说你的办公室在一个城市,但正式的办公地址在下一个城镇。我曾在一些声称位于某个城市的办公室工作,但这些办公室几乎不在一个不太知名的城市的边界之外。业主声称他们在更上层的城市,因为他们可以从行政套房的窗户看到它。证书颁发机构并不关心这种政治游戏;使用官方城市名称。
Organization ,或 O ,是大多数人搞砸的地方。贵组织的法定(legal)名称是什么?也许你称你的工作场所为The Pit,但任何认证你的组织的CA都需要完整的正式名称“The Pit of Despair,LLC”。
收集并记录这些事实。把它们写下来。创建新的证书签名请求时,请参阅文档。
TLS证书可以使用两种公钥身份验证算法,RSA和ECDSA。创建证书请求的人选择算法。
自1977年以来,Rivest-Shamir-Adleman(RSA)算法一直是首屈一指的公钥加密方法。这是几乎所有加密方法的标准技术。虽然计算能力的提高需要RSA密钥变得更长,但该算法本身经受住了密码学家多年的重点调查。
2005年,美国国家科学技术研究院(National Institute for Science and Technology —— NIST)发布了椭圆曲线数字签名算法(Elliptic Curve Digital Signature Algorithm —— ECDSA)。这种较新的算法承诺与RSA具有相同的机密性,但数字处理更少,这使得它对计算能力较低的设备和性能至关重要的环境具有吸引力。然而,ECDSA是由美国政府机构发布的,这意味着有些人会自动不信任它。密码学家对ECDSA的攻击不到二十年,虽然它一直持续到目前为止,但它缺乏RSA的悠久历史。
你应该使用哪一种?每个平台都支持RSA。如果你的目标是移动平台,或者想减少计算开销,可以考虑ECDSA。
常识宣称,如果你想要一个ECDSA证书,你需要一个拥有ECDSA根证书的CA。这不是真的。只有RSA证书的CA可以签署您的ECDSA证书。如果您选择使用ECDSA证书是因为您希望您的应用程序在与RSA斗争的较小系统上运行,那么使用由RSA CA证书签名的ECDSA证书会强制客户端执行RSA和ECDSA计算。客户端所做的工作比纯RSA证书链少,但比纯ECDSA链多。您最好选择一个可以提供免RSA证书的CA。
许多应用程序可以同时支持RSA和ECDSA证书,让您将其中一个设置为首选证书,另一个作为备份证书。购买两个证书并同时安装是一个可行的选择。
如果您以前处理过X.509证书或阅读过有关获取证书的任何文档,您可能会遇到教程,告诉您运行命令并浏览一组漂亮的提示来设置证书信息。不幸的是,这已经完全过时了——除非事实并非如此。
早在SSL出现之初,证书就将主机名正式存储在Common Name(CN)下。2000年,用于存储主机名和其他主题的主题替代名称(Subject Alternative Name)扩展获得批准,将此信息存储在通用名称中成为过时软件的后备方案。2011年,该回退从标准中删除。自从使用以来,它已经过时了四次,所以它应该是一个历史脚注,就像UUCP在给乔恩的面包车装满备份磁带并开车去镇上的校园一样。对吧?
碰巧的是,在CN中存储主机名只是基本上是死的。
由于几十年来过时和不正确的教程,其中一些是上周编写的,许多系统管理员和程序员不知道在CN中放置主机名是不推荐的。甚至一些CA仍然希望在证书请求中找到CN。其他CA接受用户遵循这些糟糕的教程。他们使用CN中的信息填充SAN字段,他们的web表单有空间添加其他SAN。其他CA希望您在证书请求中同时填充CN和SAN。
CN无法处理现代互联网主机名。CN的最大长度为63个字符。我拥有网站www.YouKeepUsingThatWordIDoNotThinkItMeansWhatYouThinkItMeans.com
。如果我试图使用完全合法的网站名称为我的网站申请TLS证书,它将失败。我必须为较短的网站订购证书,并添加我真正感兴趣的合法名称作为SAN。
此外,不检查CN的名称约束。一些客户端确实会检查CN的名称约束,但这可能会使客户端拒绝有效的证书。
各种软件对CN中主机名的持续支持阻碍了TLS和其他协议的进一步改进。人们正在积极努力将其从TLS生态系统中删除。它会消失的。检查您的基础架构是否依赖于CN中的主机名,并将其删除。
我们将跳过基于提示的方法,并在您的请求中同时包含CN和SAN,从而跳过所有混乱和面向未来的证书请求。这需要理解OpenSSL配置文件。
您的主机有一个默认的OpenSSL配置文件,告诉各种OpenSSL命令如何行为以及使用什么命令。它位于您系统的OpenSSL目录中。默认的OpenSSL目录是 /usr/local/openssl ,但几乎没有操作系统将其放在那里。查找目录的最简单方法是询问OpenSSL:
xxxxxxxxxx
$ openssl version -a | grep -i openssldir
OPENSSLDIR: "/etc/pki/tls"
这个CentOS系统将其OpenSSL配置放在 /etc/pki/tls 中。无论您的操作系统将其放置在何处,请转到此目录并查找 openssl.cnf 。
【FreeBSD14.2的OpenSSL配置文件目录在 /etc/ssl 】
配置被分成以它们所影响的命令命名的部分,用括号标记。对于 openssl req
配置,请查找名称以 req
开头的部分:
xxxxxxxxxx
[ req ]
default_bits = 2048
default_md = sha256
…
OpenSSL配置由变量、等号和变量值组成。哈希标记(#)表示注释。您不需要引用变量值,但可以使用引号来保留前导和尾随空格。如果一个值必须换行到下一行,请使用传统的反斜杠(\)。
节中的变量仅适用于该节。[ req ]
下的任何内容都会单独影响 openssl req
命令。一个配置可能有一个不同的部分,用于一个也有 default_bits
变量的不同命令,但TLS和密码学已经足够令人困惑,OpenSSL开发人员认为没有必要让它变得更糟。
为了使OpenSSL更令人兴奋,配置设置可以更改配置文件格式。在更改任何内容之前,请仔细阅读手册,并做好细致的备份。
编辑此文件可能没问题。这可能会毁了一切。这取决于你的Unix版本、安装的软件以及此时离最近的海盗船的距离。让系统范围内的默认值保持不变。大多数功能,如证书创建和管理,允许您创建一个仅包含该操作所需选项的独立配置文件。此本地配置文件中的条目将覆盖默认值。
我们将使用配置文件来创建CSR。
证书签名请求包含CA要验证的信息、该信息的数字签名和签名算法的代码。根据最佳实践,我们还将生成一个新的密钥对。您可以使用配置文件或冗长的命令行创建CSR。两者都使用 openssl req
命令。我们将在大多数示例中使用服务器证书,但也会演示客户端证书。
使用新的私钥创建续订CSR需要运行与创建第一个CSR相同的命令。无论你使用哪种方法,都要准确记录你所做的事情。如果您使用了配置文件,请保留该文件。如果你使用命令行,请编写脚本。在任何一种情况下,都要给文件一个清晰的名称,这样你明年和十年后都可以很容易地识别它。下周你不会记得这些命令,更不用说明年了,所以要妥善记录。
证书请求创建文件。在申请第一个证书之前,请考虑如何跟踪这些文件。如果你需要多个证书,将所有私钥文件命名为 private.key 会让你一头扎进火沼泽。证书的文件名应包括证书的主主机(primary host)。我为我的密钥文件命名,如用于web服务器私钥的 mwl.io-private.key 、用于证书签名请求的 mwl.io.csr 和用于完整证书的 mwl.io.crt 。如果您有许多证书,请以YYYY-MM-DD格式添加日期作为后缀。不要依赖目录来保持文件的整洁;使用文件名。如果将文件复制到错误的目录会破坏您的文件系统,则说明您的文件命名不正确。
我们将从配置文件方法开始。一旦你理解了这一点,你就拥有了纯命令行所需的所有上下文。
当我们使用 openssl req
命令创建CSR时,配置文件选项必须放在 req
部分。以下是默认 openssl.cnf 的一些示例,openssl req(1)
手册页列出了更多选项。我们将查看五个组件:主请求部分、私钥密码管理、可分辨名称(Distinguished Name)和扩展,并将它们放在一起请求证书。
req
部分包含 openssl req
命令的设置。我创建了配置文件mwl.io.conf :
xxxxxxxxxx
[ req ]
prompt = no
default_keyfile = mwl.io-private.key
distinguished_name = req_distinguished_name
req_extensions = v3_req
…
此配置文件的第一行是注释。它详细说明了此配置的用途。当需要续订证书时,我只需要查看注释即可继续。
prompt
选项控制着许多OpenSSL教程中显示的交互式对话框。通过将其设置为 no
,我们告诉OpenSSL此配置文件用于非交互式使用。
在 /etc/openssl.cnf 等通用OpenSSL配置文件中,default_keyfile
变量为在命令行上创建的私钥文件设置位置。在这里,我使用 default_keyfile
将密钥保存在特定于域的文件中。请记住,私钥既是机密的,也是证书的重要组成部分。按照第1章所述进行保护。
districted_name
说明了 openssl.cnf 如何将部分配置拉到单独的部分中。 distinguished_name
设置分为 req_distinguised_name
部分。
现代证书将SAN存储在X.509v3扩展中,因此我添加了 req_extensions
语句并将其引用到 v3_req
。
OpenSSL默认使用密码(password)加密私钥文件。(我们在第1章讨论了这种方法的优缺点。)每次创建新的CSR时,都要创建一个新的私钥。您可以不加密私钥文件,将密码放入配置文件中,或者在创建CSR时在命令行上输入密码。
为不加密私钥,请在 req
部分添加 encrypt_key
选项并将其设置为 no
。您也可以通过在命令行中添加 -nodes
选项来实现这一点,但配置文件的部分目标是简化命令行。选项 -nodes
表示“no DES”。DES很久以前就被替换了,但命令行选项保持不变以保持兼容性。
xxxxxxxxxx
encrypt_key = no
要在配置文件中包含密码,请将 output_password
选项添加到req部分。将其设置为私钥密码。
xxxxxxxxxx
output_password=haxorsKnowThisPassword
如果您没有设置这两个选项,OpenSSL在创建私钥时会提示您输入密码。
默认的 openssl.cnf 在 req_distinguised_name
下有一大堆示例条目。它们是为以CN为中心的证书而设计的。如果您是从配置文件创建证书,则格式会发生变化。(从技术上讲,将prompt设置为no会更改配置文件格式,但这就是该设置的目的。)
在 req_distinguised_name
部分下,列出可分辨名称的所有组件。对于EV或OV证书,包括国家、州、城市、组织和通用名称。
xxxxxxxxxx
[ req_distinguished_name ]
C = US
ST = Michigan
L = Detroit
O = Inconceivable Incorporated
OU = IT
CN = mwl.io
我正在创建DV证书,所以我只需要通用名。是的,不推荐将主机名存储在CN中。不管怎样,我们都会去做的。
xxxxxxxxxx
[ req_distinguished_name ]
CN = mwl.io
CN的存在只是为了与传统兼容,但 wow ,有很多传统的东西吗。
X.509的版本3具有各种扩展。有用于定义如何使用证书的扩展、用于设置约束的扩展、定义CRL位置的扩展以及告诉您在哪里可以找到CA策略的扩展。很容易看到这些东西,然后陷入困境,试图找出哪些应该适用于您的证书签名请求。
不要那样做。
可以在签名阶段应用扩展。您的CA将添加自己的信息。他们将实施限制,例如“此证书不能用于签署更多证书”和“仅适用于web应用程序”。仅对应用程序文档明确声明需要的内容请求扩展,并使CA拒绝您。
扩展的首选是主题替代名称(Subject Alternative Names —— SAN)。这是标识证书有效主机的标准位置。在 v3_req
部分确定证书所需的名称。SAN位于 subjectAltName
字段中。在此字段中列出多个SAN,用逗号分隔。每个SAN声明都有两个部分,SAN的类型和值,用冒号分隔:
xxxxxxxxxx
[ v3_req ]
subjectAltName = DNS:mwl.io,DNS:www.mwl.io,DNS:cdn.mwl.io
该CSR有三个SAN: mwl.io
、 www.mwl.io
和 cdn.mwl.io
。
注意:我将通用名称作为SAN包含在内。SAN是获取有效名称的标准方法。支持它。
CSR可以包括许多SAN。定义主题备选名称的标准(RFC 5280)没有设置证书可以支持的SAN的最大数量。但是,证书颁发机构可以并且确实设置了限制。100是一个常见的限制,但一些CA确实支持数千个——当然,每个名字的费用很低。
虽然从技术上讲,你可以在配置文件的一行中放置数千个条目,但实际上,这就像在死亡线上反对西西里人一样愚蠢。如果你想让每个主机名都在自己的行上,请创建一个 openssl.cnf 数组,并在该数组中创建SAN条目:
xxxxxxxxxx
…
[ v3_req ]
subjectAltName = @alt_names
[alt_names]
…
在 v3_req
部分下, subjectAltName
设置为 @alt_names
。这告诉OpenSSL寻找另一个部分,称为 alt_names
,我们接下来定义它。alt_names
下的每个条目都有这种格式:
type.number = hostname
我们所有的SAN都是DNS类型。 x509v3_config(5)
中讨论了其他类型,但只有DNS适用于我们大多数人。(SAN IP地址类型似乎很有趣,但没有公开受信任的CA会接受具有证书的证书。) numver 是一个递增的整数,它将该值分配到阵列中的一个位置。你可以跳过数字,但不要重复;将多个值放在阵列中的一个空间中是行不通的。最后,给出要在SAN中显示的 hostname 。
xxxxxxxxxx
[alt_names]
DNS.1 = mwl.io
DNS.2 = www.mwl.io
DNS.3 = mwlucas.org
DNS.4 = tiltedwindmillpress.org
DNS.5 = michaelwarrenlucas.com
…
在大型组织中,阵列支持简化了CSR自动化。您可以编写一个脚本,从数据库中提取主机名并创建配置文件。虽然SAN以数组顺序出现在CSR中,但该顺序不影响验证,也不影响TLS。
我们将在第3章讨论通配符证书及其众多缺点。如果您坚持创建一个,请将通配符列为SAN:
xxxxxxxxxx
[alt_names]
DNS.1 = mwl.io
DNS.2 = www.mwl.io
DNS.3 = *.api.mwl.io
DNS.4 = *.cdn.mwl.io
这将创建一个适用于 mwl.io
中选定主机名的证书,以及两个子域名的通配符。此证书可以安装在我的web服务器上,也可以安装在 api.mwl.io
和 cdn.mwl.io
中的任何主机上。我还必须在每台机器上安装私钥,因此一个私钥的危险会危及整个网络。通配符证书不仅会给主机带来风险,还会给整个生态系统带来风险。
综上所述,带有ECDSA密钥的证书的完整配置文件如下:
xxxxxxxxxx
[ req ]
prompt = no
default_keyfile = mwl.io-private.key
distinguished_name = req_distinguished_name
req_extensions = v3_req
[ req_distinguished_name ]
CN = mwl.io
[ v3_req ]
subjectAltName = @alt_names
[alt_names]
DNS.1 = mwl.io
DNS.2 = www.mwl.io
DNS.3 = *.api.mwl.io
DNS.4 = *.cdn.mwl.io
一旦你有了一个完整的配置文件,请确保你有一个参数文件。
椭圆曲线密码学与RSA不同。从系统管理员的角度来看,它们似乎是一样的:你保护私钥并泄露公钥。您向CA提交CSR并取回证书。您丢失了私钥密码,必须购买新证书。一切都好。
ECDSA由椭圆曲线定义。椭圆曲线是一种数学构造。ECDSA证书使用一组众所周知的椭圆曲线之一。这些众所周知的曲线都有一个名字。最受支持的曲线是NIST定义的P-256、P-384和P-251。您可能会看到这些曲线被错误地描述为长度,但曲线不是比特长度。(如果您需要系统支持的椭圆曲线的完整列表,请运行 openssl ecparam -list_curves
。)如果您对椭圆曲线一无所知,只知道ECDSA证书更适合小型设备,请使用曲线P-256。
在生成ECDSA CSR之前,您需要所选曲线的参数(parameters )文件。曲线参数描述曲线。参数文件不是密钥,也不是机密文件。它有点像 /etc/protocols 文件,但mathy。每个人都知道里面有什么。OpenSSL的genpkey命令通常用于生成私钥,也会写出参数文件。
$ openssl genpkey -genparam -out filename.pem -algorithm ec -pkeyopt ec_paramgen_curve:curvename
您只需要做出两个决定:创建的文件的名称(如 -out
所示)和使用哪条曲线。在这里,我创建了一个P-256参数文件 ec256-params.pem :
xxxxxxxxxx
$ openssl genpkey -genparam -algorithm ec -out ec256-params.pem -pkeyopt ec_paramgen_curve:P-256
如果你四处看看,你会发现DHE使用了类似的参数文件。如果需要,您也可以使用 openssl genpkey
生成这些文件。
我们有一个配置文件和一个参数文件。我们现在可以使用openssl-req命令创建ECDSA证书签名请求。
$ openssl req -newkey ec:parameters.pem -config filename.conf -out filename.csr
-newkey
选项使用参数文件中的参数创建一个新密钥。我给出了带 -config
的配置文件和带 -out
的目标文件。
在这里,我使用我们刚刚创建的ECDSA配置文件和参数文件为我的域 mwl.io
创建ECDSA CSR:
xxxxxxxxxx
$ openssl req -newkey ec:ec256-params.pem -config mwl.io.conf -out mwl.io.csr
Generating an EC private key
writing new private key to 'mwl.io-private.key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
文件 mwl.io.csr 现在包含ECDSA CSR。
一些教程建议创建一个新密钥,然后使用该密钥创建CSR。这是有效的,但会导致要打更多的字。
通过编写配置文件并运行命令来创建RSA CSR。
RSA CSR的配置文件几乎与ECDSA版本相同,只有一个例外。您必须使用 default_bits
选项设置RSA密钥的长度。如果需要非默认哈希算法,请使用 default_md
指定。
在此配置中,我设置了2048位的默认RSA密钥长度和硬代码SHA256哈希。其余部分与ECDSA密钥完全相同。
xxxxxxxxxx
[ req ]
prompt = no
default_bits = 2048
default_md = sha256
default_keyfile = mwl.io-private.key
distinguished_name = req_distinguished_name
req_extensions = v3_req
[ req_distinguished_name ]
CN = mwl.io
[ v3_req ]
subjectAltName = @alt_names
[alt_names]
DNS.1 = mwl.io
DNS.2 = www.mwl.io
我没有指定任何密码管理规定,因此CSR创建命令将提示我输入密码。使用此文件,我可以生成RSA CSR。
使用配置文件中的 openssl req
命令生成RSA证书请求。与ECDSA不同,您不需要参数文件。
$ openssl req -newkey rsa -config filename.conf -out filename.csr
-newkey
参数告诉 req
创建一个新的私钥。我们给它一个参数: rsa
来创建rsa密钥。 -config
参数设置配置文件,而 -out
允许您为完成的CSR提供文件名。
在这里,我使用配置文件 mwl.io.conf 为我的域 mwl.io
生成证书签名请求:
xxxxxxxxxx
$ openssl req -newkey rsa -config mwl.io.conf -out mwl.io.csr
Generating a RSA private key
.............+++++
........................................................................+++++
writing new private key to 'mwl.io-private.key'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
我输入了两次密码短语,并获得了包含我的RSA CSR的文件 mwl.io.csr 作为奖励。
客户端证书的过程和算法与服务器证书相同,但证书中的信息略有不同。与服务器证书不同,客户端证书中必须出现的信息没有定义的标准。不同的应用程序可能需要不同的细节。我描述的是一种常见用法,但请仔细检查您的文档以了解任何特殊需求。
许多应用程序都包含自己的CA,用于签署客户端证书。您不希望您的VPN设备接受由任何公共CA签名的所有客户端证书。这样的设备应该只接受它签名的证书。这样的系统可能有自己的生成CSR的系统。
这是一个客户端证书的配置文件,用于向公司VPN认证用户。证书需要用户名作为Common Name,并且证书必须包含用户的电子邮件地址。当CN包含主机名时,可分辨名称可以包含用户的电子邮件地址作为emailAddress属性。这现在已经过时了,但它仍然像CN中的主机名一样存在。给出电子邮件地址的正确方法是使用rfc822Name值作为主题备用名称,就像我们使用主机名一样。我将在配置文件中使用这两种方法,但如果您的应用程序允许您从可分辨名称中删除emailAddress,请这样做。
该配置类似于服务器证书请求的配置。我可以在可分辨名称中添加组织信息,但这通常是不必要的。
xxxxxxxxxx
[ req ]
prompt = no
default_bits = 2048
default_keyfile = client-private.key
distinguished_name = req_distinguished_name
[ req_distinguished_name ]
CN = Michael W Lucas
emailAddress = mwl@mwl.io
[ v3_req ]
subjectAltName = email:mwl@mwl.io
OpenSSL不在乎证书请求是针对客户端还是服务器。CSR的创建也是一样的。
xxxxxxxxxx
$ openssl req -newkey rsa -config client.conf -out client.csr
文件 client.csr 包含我的证书签名请求。
人们使用的客户端证书必须有密码。客户端证书的目的是对用户进行身份验证。此证书将始终由人类使用,最常用于笔记本电脑等移动设备。任何窃取笔记本电脑的人都可以使用未加密的私钥。如果你的组织中有一位老板抱怨说,如果不输入密码,他们就无法无缝地双击VPN应用程序,问问他们为什么要冒着公司诚信的风险来躲避抢劫者。
应用程序使用的客户端证书不需要密码。也许您的邮件服务器必须通过服务提供商的邮件服务器中继出站电子邮件,并且必须使用证书对该中继进行身份验证。以保护服务器上任何其他私钥的方式保护证书的私钥就足够了。
如果CN被SAN取代,您的证书中是否需要它们?不。您可以创建没有主题(Subjects)或可分辨名称(Distinguished Names)的证书。
虽然可分辨名称对于高度验证的证书很重要,但对于DV证书请求,您可以完全跳过它。较旧的客户端可能在证书方面遇到问题,但无论如何都应该升级。这是一个没有可分辨名称的客户端证书的配置文件。
xxxxxxxxxx
[ req ]
default_bits = 2048
default_keyfile = mwlucas-private.key
distinguished_name = req_distinguished_name
req_extensions = v3_req
[ req_distinguished_name ]
[ v3_req ]
subjectAltName = email:mwl@mwl.io
这些的主要烦恼是你不能将prompt设置为no。这会触发OpenSSL安全检查。相反,您可以在命令行上使用 -subj
将可分辨名称设置为 /
。这只是DN的前斜线,后面没有任何内容。命令行在其他方面是相同的。
xxxxxxxxxx
$ openssl req -newkey rsa -config client.conf -out client.csr -subj /
如果你检查CSR,你会看到它在主题备选名称中有电子邮件地址,但甚至没有主题字段。
找个时间试试。看看你的软件坏了多少。对开发商大喊大叫。
配置文件并不难,但有时您需要完全在命令行上创建CSR。这个命令并不漂亮。创建临时配置文件的工作量要小得多,并增加了您在创建CSR之前仔细检查工作的能力。但是,如果您有一个自动创建CSR的过程,则需要该过程来组装和运行命令行。这仅适用于OpenSSL 1.1.1及更高版本。
命令行看起来像这样:
xxxxxxxxxx
$ openssl req -newkey algo:length \
-keyout privatekey.pem -out request.csr \
-subj /C=country/ST=state/L=city/O=organization/CN=hostname \
-addext "subjectAltName=DNS:hostname,DNS:hostname"
-newkey
参数需要两个冒号分隔的参数,算法和密钥长度或参数文件。
-keyout
参数设置要写入私钥的文件的名称。如果不想加密私钥,请添加 -nodes
标志。
-subj
参数允许您设置可分辨名称。如果你有一个主题,在每个目录条目前加一个斜线。使用 -subj /
技巧创建一个没有主题的证书,并依赖SAN。
如果要创建EV或OV证书,则必须设置C、ST、L和O值。C 代表国家,必须是ISO 3166双字母代码。 ST 代表州或省,应为全名。 L 代表组织合法所在地或城市。 O 代表组织或完整的合法企业名称。 OU 代表组织单位或组织内的部门。您还将看到这些名称为 countryName 、 stateOrProvinceName 、 organizationName 和 organizationalUnitName 。标签可以互换使用。
-addext
标志允许您将X.509v3扩展添加到CSR中。SAN使用SubjectAltName扩展。按照您在配置文件中的单行中的方式精确指定它们。如果您有几十个SAN,请非常小心地键入或使用配置文件。
在这里,我为 mwl.io
创建了一个RSA证书,为 mwl.io
和 www.mwl.io
添加了SAN,并为子域名 cdn.mwl.io
添加了通配符。我必须在组织和位置信息中转义空格。
xxxxxxxxxx
$ openssl req -newkey rsa:2048 -keyout www-private.pem -out www-request.csr \
-subj /C=FL/ST=Humperdinck/L=Florin\ City/O=Inconceivable\ Incorporated/CN=mwl.io \
-addext "subjectAltName=DNS:mwl.io,DNS:www.mwl.io,DNS:*.cdn.mwl.io"
同样,如果您使用的是DV证书,您可以跳过所有组织信息,只提供CN。
xxxxxxxxxx
$ openssl req -newkey rsa:2048 -keyout www-private.pem -out www-request.csr \
-subj /CN=mwl.io \
-addext "subjectAltName=DNS:mwl.io,DNS:www.mwl.io,DNS:*.cdn.mwl.io"
我强烈建议将这些命令放在命名良好、注释良好的shell脚本中,这样您或您的继任者就可以在组织的其余时间里每年轻松生成新的CSR。
在向任何CA发送任何CSR之前,请仔细检查您的工作内容。
您仔细地将所有正确的数据输入到一个恶意的OpenSSL命令中,并生成了一个据称包含您的CSR的文件。该文件包含一堆乱码,周围有标记,分别声明“开始证书请求”和“结束证书请求”。你如何检查你的CSR以确保它是正确的?
与其他OpenSSL命令一样, openssl req
可以读取文件并将其转换为其他格式。使用 -in
提供包含CSR的文件名,使用 -text
生成文本输出。您可以添加 -noout
以跳过在输出中打印证书签名请求。所有这些应该与我们的其他OpenSSL命令看起来很熟悉。在这里,我仔细检查了我的域名 mwl.io
的CSR:
xxxxxxxxxx
$ openssl req -in mwl.io.csr -noout -text
Certificate Request:
Data:
Version: 1 (0x0)
Subject: CN = www.mwl.io
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
…
Subject 字段显示CSR中包含的组织数据,如公司名称和主机名。下面是公钥信息,包括密钥算法,然后是SAN和其他扩展。
现在,您可以将CSR提交给您的证书颁发机构。如果你使用ACME,这会自动发生——就像创建CSR一样。如果您使用的是商业CA,则必须遵循CA的CSR签名程序。作为交换,您将获得一个闪亮的新X.509证书!
安装证书之前,请先查看证书。CA可能会添加自己的扩展名,或删除您请求的一些扩展名。验证证书是否包含您需要的所有内容。
现在,在您的应用程序中安装证书。这本书不能帮助具体的应用程序,但这里有一些一般性的建议。以证书通用名中的完全限定域名命名文件。在生产环境中,我的 mwl.io
证书名为 mwl.io.crt ,私钥是 mwl.io.key 。保护密钥文件,最好放在只能由应用程序和root读取的目录中。
在Unix系统上,您可以将所有证书放在 /etc/certs 这样的目录中。这样,任何应用程序都可以访问此主机的证书。私钥可以进入 /etc/certs/keys 。将该目录归root所有,但创建一个可以读取该目录及其文件的组。将应用程序用户添加到该组。
备份您的证书。仔细检查备份。雇佣一个巨人来保护备份。
重复使用私钥是不好的做法。但是,你怎么能确定一些流氓没有遵循那些过时的互联网教程,重用私钥而不是生成新的私钥呢?如果你的CSR归档系统不完善,你必须弄清楚哪个证书属于哪个私钥,你该如何整理?
这些是具有相同解决方案的单独问题。
键对(keypair)模数(modulus)是其独特的数值特征之一。你不需要知道数学,只需要知道它是独一无二的。您可以使用OpenSSL的 -module
选项从文件中提取模数。模数是一个非常长的数字,但您可以使用 openssl md5
轻松检查它。(虽然MD5不再是加密安全的,但它完全可用作非加密哈希。)在这里,我从证书、私钥和CSR中提取密钥模数。
xxxxxxxxxx
$ openssl x509 -noout -modulus -in server.crt | openssl md5
d261c8136ff4154881814df84cc0829a
$ openssl rsa -noout -modulus -in server.key | openssl md5
d261c8136ff4154881814df84cc0829a
$ openssl req -noout -modulus -in server.csr | openssl md5
2606bbdc0f7b099117342eefd049d5b0
证书和密钥的哈希以 d 开头。CSR的哈希以 2 开头。我们可以停止寻找;此CSR未用于创建此证书。
每个组织都有创建密钥的独特程序,所以我无法告诉你在哪里实施此类检查以确保私钥不被重用。最坏的情况是,你可以把它们放在你的网络管理系统中。一年多没有改变的证书模数表明它重用了之前的私钥。不过,最好在部署之前抓住这些。
说到自动化,让我们自动获得一些证书。