题 证书颁发机构根证书到期和续订


2004年,我在Linux上使用OpenSSL和OpenVPN提供的简单管理脚本建立了一个小型证书颁发机构。根据我当时发现的指南,我将根CA证书的有效期设置为10年。从那以后,我签署了许多OpenVPN隧道,网站和电子邮件服务器的证书,所有这些证书的有效期也都是10年(这可能是错误的,但我当时并不知道更好)。

我找到了许多关于设置CA的指南,但是关于其管理的信息很少,特别是关于根CA证书到期时必须做什么的信息,这将在2014年的某个时间发生。所以我有以下内容问题:

  • 在根CA证书到期后,有效期延长的证书一旦到期就会变为无效,或者它们是否会继续有效(因为它们是在CA证书的有效期内签署的)?
  • 更新根CA证书并确保在到期时平稳过渡需要哪些操作?
    • 我可以以不同的方式重新签署具有不同有效期的当前根CA证书,并将新签名的证书上载到客户端,以便客户端证书保持有效吗?
    • 或者我是否需要将所有客户端证书替换为由新的根CA证书签名的新证书?
  • 应该何时更新根CA证书?接近到期,或到期前的合理时间?
  • 如果根CA证书的更新成为主要工作,那么我现在可以做些什么来确保在下次续订时更顺利的过渡(当然,将有效期设置为100年)?

由于我对某些客户端的唯一访问是通过使用当前CA证书签名的证书的OpenVPN隧道,所以情况稍微复杂一些,所以如果我必须替换所有客户端证书,我将需要复制新文件到客户端,重新启动隧道,交叉我的手指,并希望它后来出现。


87
2017-08-30 08:34






答案:


在根CA上保留相同的私钥允许所有证书继续针对新根成功验证;所有你需要的是信任新的根。

证书签名关系基于私钥的签名;在生成新的公共证书时保留相同的私钥(并且隐含地,相同的公钥),具有新的有效期和根据需要改变的任何其他新属性,保持信任关系。 CRL也可以从旧证书继续到新证书,因为它们就像证书一样,由私钥签名。


所以,让我们验证!

创建根CA:

openssl req -new -x509 -keyout root.key -out origroot.pem -days 3650 -nodes

从中生成子证书:

openssl genrsa -out cert.key 1024
openssl req -new -key cert.key -out cert.csr

签署儿童证书:

openssl x509 -req -in cert.csr -CA origroot.pem -CAkey root.key -create_serial -out cert.pem
rm cert.csr

全部设置,正常的证书关系。让我们验证信任:

# openssl verify -CAfile origroot.pem -verbose cert.pem
cert.pem: OK

好的,现在让我们说10年过去了。让我们从同一个根私钥生成一个新的公共证书。

openssl req -new -key root.key -out newcsr.csr
openssl x509 -req -days 3650 -in newcsr.csr -signkey root.key -out newroot.pem
rm newcsr.csr

而且......它有效吗?

# openssl verify -CAfile newroot.pem -verbose cert.pem
cert.pem: OK

但为什么?它们是不同的文件,对吧?

# sha1sum newroot.pem
62577e00309e5eacf210d0538cd79c3cdc834020  newroot.pem
# sha1sum origroot.pem
c1d65a6cdfa6fc0e0a800be5edd3ab3b603e1899  origroot.pem

是的,但是,这并不意味着新公钥不会以加密方式匹配证书上的签名。不同的序列号,相同的模数:

# openssl x509 -noout -text -in origroot.pem
        Serial Number:
            c0:67:16:c0:8a:6b:59:1d
...
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:bd:56:b5:26:06:c1:f6:4c:f4:7c:14:2c:0d:dd:
                    3c:eb:8f:0a:c0:9d:d8:b4:8c:b5:d9:c7:87:4e:25:
                    8f:7c:92:4d:8f:b3:cc:e9:56:8d:db:f7:fd:d3:57:
                    1f:17:13:25:e7:3f:79:68:9f:b5:20:c9:ef:2f:3d:
                    4b:8d:23:fe:52:98:15:53:3a:91:e1:14:05:a7:7a:
                    9b:20:a9:b2:98:6e:67:36:04:dd:a6:cb:6c:3e:23:
                    6b:73:5b:f1:dd:9e:70:2b:f7:6e:bd:dc:d1:39:98:
                    1f:84:2a:ca:6c:ad:99:8a:fa:05:41:68:f8:e4:10:
                    d7:a3:66:0a:45:bd:0e:cd:9d
# openssl x509 -noout -text -in newroot.pem
        Serial Number:
            9a:a4:7b:e9:2b:0e:2c:32
...
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:bd:56:b5:26:06:c1:f6:4c:f4:7c:14:2c:0d:dd:
                    3c:eb:8f:0a:c0:9d:d8:b4:8c:b5:d9:c7:87:4e:25:
                    8f:7c:92:4d:8f:b3:cc:e9:56:8d:db:f7:fd:d3:57:
                    1f:17:13:25:e7:3f:79:68:9f:b5:20:c9:ef:2f:3d:
                    4b:8d:23:fe:52:98:15:53:3a:91:e1:14:05:a7:7a:
                    9b:20:a9:b2:98:6e:67:36:04:dd:a6:cb:6c:3e:23:
                    6b:73:5b:f1:dd:9e:70:2b:f7:6e:bd:dc:d1:39:98:
                    1f:84:2a:ca:6c:ad:99:8a:fa:05:41:68:f8:e4:10:
                    d7:a3:66:0a:45:bd:0e:cd:9d

让我们再进一步验证它是否在真实世界证书验证中工作。

启动一个Apache实例,让它一试(debian文件结构,根据需要调整):

# cp cert.pem /etc/ssl/certs/
# cp origroot.pem /etc/ssl/certs/
# cp newroot.pem /etc/ssl/certs/
# cp cert.key /etc/ssl/private/

我们将这些指令设置为a VirtualHost 听443 - 记住, newroot.pem 根证书甚至不存在时 cert.pem 生成并签名。

SSLEngine on
SSLCertificateFile /etc/ssl/certs/cert.pem
SSLCertificateKeyFile /etc/ssl/private/cert.key
SSLCertificateChainFile /etc/ssl/certs/newroot.pem

我们来看看openssl是如何看待它的:

# openssl s_client -showcerts -CAfile newroot.pem -connect localhost:443

Certificate chain
 0 s:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=server.lan
   i:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=root
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
 1 s:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=root
   i:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=root
-----BEGIN CERTIFICATE-----
MIICHzCCAYgCCQCapHvpKw4sMjANBgkqhkiG9w0BAQUFADBUMQswCQYDVQQGEwJB
...
-----END CERTIFICATE-----
(this should match the actual contents of newroot.pem)
...
Verify return code: 0 (ok)

好的,使用MS的加密API的浏览器怎么样?必须信任root,首先,然后使用新root的序列号就可以了:

newroot

而且,我们仍然应该使用旧的根。切换Apache的配置:

SSLEngine on
SSLCertificateFile /etc/ssl/certs/cert.pem
SSLCertificateKeyFile /etc/ssl/private/cert.key
SSLCertificateChainFile /etc/ssl/certs/origroot.pem

在Apache上完全重启,重新加载不会正确切换证书。

# openssl s_client -showcerts -CAfile origroot.pem -connect localhost:443

Certificate chain
 0 s:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=server.lan
   i:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=root
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
 1 s:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=root
   i:/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=root
-----BEGIN CERTIFICATE-----
MIIC3jCCAkegAwIBAgIJAMBnFsCKa1kdMA0GCSqGSIb3DQEBBQUAMFQxCzAJBgNV
...
-----END CERTIFICATE-----
(this should match the actual contents of origroot.pem)
...
Verify return code: 0 (ok)

而且,使用MS加密API浏览器,Apache会显示旧的root,但新的root仍然在计算机的受信任的根存储中。它会自动找到它并根据可信(新)根验证证书,尽管Apache呈现不同的链(旧根)。从受信任的根剥离新根并添加原始根证书后,一切都很好:

oldroot


就是这样了!在续订时保留相同的私钥,交换新的受信任的根,几乎所有 只是工作。祝好运!


124
2017-09-04 18:40



无论如何,如果您只是要重用相同的私钥,那么创建新根证书的重点是什么?如果你一遍又一遍地这样做,那么甚至证书的到期日有什么意义呢?我认为root过期用于强制管理员制作一个更新的(最可能更强大的)私钥,这种私钥对于试图打破密钥的不断前进的机器更安全。 20年前生产的40位密钥不够安全 - jvhashe
@jvhashe如果根证书不再具有加密强度,那么无论其到期日期如何,你都应该摆脱它。如果你正在生成自己的根,那么没有什么可以阻止你将它设置为过去几百年过去,当你不再在这个星球上时。到期几乎与根证书无关 - 对于子证书,到期时间与加密强度无关(要求准备在10月撤销所有1024位证书的CA) - 请参阅 这里 了解更多信息。 - Shane Madden♦
除了上述内容之外,我发现此方法的序列号需要相同才能工作。 - Scott Presnell
-set_serial 01  - WTF ??? 你不能重复使用序列号。你有没有咨询过 RFC 4158,Internet X.509公钥基础结构:认证路径构建?或者你只是随着时间的推移而弥补?在开始构建路径时,您不知道用户代理中导致的问题。 - jww
@jww你读过答案吗?这只是密码学工作的一个证明。为了测试新旧root证书之间的关系,该命令实际上只是生成一个我们可以在以后验证的测试证书。如果有人 是 直接使用这些命令,我​​当然希望有些东西能够破解,并且他们意识到他们需要在盲目地运行它之前注意某些事物的背景(或者是关于是否 01 是实验室中可接受的序列号)。 - Shane Madden♦


我注意到原始CA密钥的续订证书中可能缺少CA扩展。 这对我来说更合适(它创造了一个 ./renewedselfsignedca.conf 其中定义了v3 CA扩展,以及 的ca.key 和 ca.crt 假定是原始CA密钥和证书):

openssl x509 -x509toreq -in ca.crt -signkey ca.key -out renewedselfsignedca.csr
echo -e "[ v3_ca ]\nbasicConstraints= CA:TRUE\nsubjectKeyIdentifier= hash\nauthorityKeyIdentifier= keyid:always,issuer:always\n" > renewedselfsignedca.conf
openssl x509 -req -days 1095 -in renewedselfsignedca.csr -signkey ca.key -out renewedselfsignedca.crt -extfile ./renewedselfsignedca.conf -extensions v3_ca

13
2018-04-22 10:31



这是一个非常有用的补充。如果您在原始根ca上有任意设置,那么实际有效的答案不会为我提供足够兼容的证书。 - Theuni
借调,非常有帮助。另外一点:就像Scott Presnell在接受回答的评论中一样,我还必须手动指定续订证书的十六进制序列号,以便与旧证书匹配。这意味着要加入 -set_serial 0xdeadbeefabba (不是真正的序列号:))到后面的x509命令。只有这样,我的客户端证书才能成功验证续订的CA证书。 - JK Laiho
此方法更容易,因为它保留与先前证书相同的信息。 - lepe
我为此解决方案创建了一个脚本加-set_serial - 请参阅我的回答 - Wolfgang Fahl
这个答案为我节省了大量的工作,在花了将近一天的时间处理这个问题之后,我几乎要放弃了,我为此向你倾诉! - Onitlikesonic


扩展root有效期的基本模式(需要公共X.509和相关私钥):

从公共X.509和私钥生成CSR:

openssl x509 -x509toreq -in XXX.crt -signkey XXX.key -out XXX.csr

使用私钥重新签名CSR:

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

2
2018-01-22 16:35





当您的根证书到期时,您使用它签署的证书也是如此。您必须生成新的根证书并使用它签署新证书。如果你不想每隔几年重复一次这个过程,那么唯一真正的选择就是将根证书上的有效日期延长十年或二十年:我为自己生成的根我设定了二十年。

您无法“续订”根证书。你所能做的就是生成一个新的。

在旧的根目录到期之前至少一年或两年生成一个新的根目录,这样你就有时间在没有时间限制的情况下进行转换,如果出现问题。这样你就可以暂时切换回原来的证书,直到你解决了新的问题。

就VPN隧道而言,我会设置几个测试平台服务器进行试验,这样您就可以在使用客户端计算机之前准确了解自己需要做什么。


0
2017-09-03 23:59



这个回复 似乎建议通过重新使用其密钥来更新根证书。但我怀疑这与从头开始没有什么不同,因为新证书将具有不同的签名,因此不会验证现有的客户端证书。 - Remy Blank
是的,您可以延长有效期...并且比重新创建所有pki,客户端证书和重新启动新根更少工作... - ggrandes
发布新的终端实体证书的部分不一定正确。它取决于权限密钥标识符(AKID)在下属CA和最终实体证书中的表示方式。如果AKID是基于 {专有名称,序列号},然后将实现连续性。另见 RFC 4518,Internet X.509公钥基础结构:认证路径构建。 - jww


@Bianconiglio plus -set_serial为我工作。 我的服务器只是内联网所以我并不担心副作用是什么,我现在有时间研究“正确”的解决方案。

我使用了以下可配置脚本。只需设置变量CACRT,CAKEY和NEWCA。

# WF 2017-06-30
# https://serverfault.com/a/501513/162693
CACRT=SnakeOilCA.crt
CAKEY=SnakeOilCA.key
NEWCA=SnakeOilCA2017
serial=`openssl x509 -in $CACRT -serial -noout | cut -f2 -d=`
echo $serial
openssl x509 -x509toreq -in $CACRT -signkey $CAKEY -out $NEWCA.csr
echo -e "[ v3_ca ]\nbasicConstraints= CA:TRUE\nsubjectKeyIdentifier= hash\nauthorityKeyIdentifier= keyid:always,issuer:always\n" > $NEWCA.conf
openssl x509 -req -days 3650 -in $NEWCA.csr -set_serial 0x$serial -signkey $CAKEY -out $NEWCA.crt -extfile ./$NEWCA.conf -extensions v3_ca
openssl x509 -in $NEWCA.crt -enddate -serial -noout

0
2018-06-30 17:33





我们遇到了同样的问题,这就是我们的情况,因为Debian服务器是最新的,openSSL有这个问题:

https://en.wikipedia.org/wiki/Year_2038_problem

Debian 6的最新OpenSSL版本带来了这个问题。 所有在23.01.2018之后创建的证书都会产生一个Vality:1901年!

解决方案是更新OpenSSL。您可以再次为客户端创建配置文件(带有证书)。


0
2018-03-09 10:38