证书颁发机构根证书的有效期和续订


96

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

我找到了许多有关建立CA的指南,但是关于其管理的信息很少,尤其是有关根CA证书到期时必须执行的操作的信息,这将在2014年的某个时候发生。因此,我有以下内容问题:

  • 根CA证书到期后具有有效期的证书会在根证书到期后立即失效,还是会继续有效(因为它们是在CA证书的有效期内签名的)?
  • 需要什么操作来更新根CA证书并确保在其有效期内顺利过渡?
    • 是否可以以不同的有效期以某种方式重新签名当前的根CA证书,并将新签名的证书上传到客户端,以便客户端证书保持有效?
    • 还是我需要用新的根CA证书签名的新客户端证书替换所有客户端证书?
  • 根CA证书应何时更新?即将到期或在到期前的合理时间?
  • 如果根CA证书的更新成为一项主要工作,那么我现在可以做些什么更好的措施,以确保在下一次更新时进行更平滑的过渡(当然,将有效期设置为100年)?

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

Answers:


142

在根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/

我们将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的浏览器怎么样?首先要信任根,然后使用新根的序列号就可以了:

新根

而且,我们也应该使用旧的根。切换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 crypto API浏览器,Apache可以显示旧的根目录,但是新的根目录仍在计算机的受信任的根存储区中。即使Apache提供了不同的链(旧根),它也会自动找到它并针对受信任的(新)根验证证书。在从受信任的根目录中剥离新的根目录并添加原始的根证书之后,一切都很好:

老根


就是这样了!续订时保留相同的私钥,交换新的受信任的根,它几乎就可以正常工作。祝好运!


2
无论如何,如果您只是要重用相同的私钥,那么创建新的根证书有什么意义呢?如果您一遍又一遍地这样做,那么即使有证书的到期日期又有什么意义呢?我认为根到期是用来迫使管理员创建一个新的(很可能是更强壮的)私钥,它对于试图破解密钥的不断发展的计算机来说更加安全。20年前制作的40位密钥不够安全
jvhashe13年

2
@jvhashe如果根证书的加密强度不再足够,则无论其到期日期如何,都应删除它。如果您要生成自己的根,没有什么可以阻止您将其设置为在不再存在于地球上的数百年后过期。到期与根证书几乎没有关系-对于子证书,到期也与加密强度无关(询问准备在十月撤销所有1024位证书的CA)- 有关更多信息,请参见此处
Shane Madden

3
除上述内容外,我发现序列号也必须相同才能使用此方法。
Scott Presnell 2014年

2
-set_serial 01-WTF ???您无法重复使用序列号。您甚至还参考了RFC 4158,Internet X.509公钥基础结构:认证路径构建吗?还是只是在进行过程中加以弥补?您不知道用户代理开始构建路径时给他们带来的问题。

1
@jww你读了答案吗?这只是加密技术起作用的事实的证明。实际上,该命令只是生成一个测试证书,我们可以稍后对其进行验证,以测试新旧根证书之间的关系。如果有人直接使用这些命令,我当然希望打破的东西,他们认识到,他们需要留意过盲目运行它(或起飞的手柄是否某事的情况下01是在实验室可接受串行)。
Shane Madden

14

我注意到,原始CA密钥的更新证书中可能缺少CA扩展。这对我来说更合适(它创建了一个./renewedselfsignedca.conf,其中定义了v3 CA扩展名,并且ca.keyca.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

2
这是非常有用的补充。如果您在原始根ca上进行了任意设置,那么实际有效的答案对我而言就不会产生足够兼容的证书。
Theuni 2014年

1
其次,非常有帮助。另一个补充:像Scott Presnell在接受的答案的注释中一样,我还必须手动指定更新证书的十六进制序列号,以使其与旧证书相匹配。这意味着-set_serial 0xdeadbeefabba在后面的x509命令中添加(不是真正的序列号:))。只有这样,我的客户证书才可以针对更新的CA证书进行成功验证。
JK Laiho 2015年

该方法比以前的证书保留相同的信息,因此更容易。
lepe

我为该解决方案创建了脚本,并添加了-set_serial-请参见我的答案
Wolfgang Fahl,

在将这个问题花了将近一天的时间之后,这个答案为我节省了很多工作。我几乎要放弃了,为此,我向你致敬!
Onitlikesonic

2

延长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

1

@Bianconiglio加-set_serial为我工作。我的服务器仅是Intranet,因此我不必担心很多副作用,现在我有时间来研究“适当的”解决方案。

我使用了以下可配置脚本。只需设置变量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

当您的根证书过期时,与您签署的证书也将过期。您将必须生成一个新的根证书并用它签名新证书。如果您不想每隔几年重复一次此过程,唯一的实际选择是将根证书上的有效日期延长大约十年或二十年:我为自己使用而生成的根定为二十年。

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

在您的旧根到期之前至少一两年内生成一个新根,这样,如果出现问题,您就可以有足够的时间进行转换而不会遇到时间障碍。这样一来,您始终可以暂时切换回旧证书,直到解决新证书时遇到的麻烦。

就VPN隧道而言,我将设置几个测试平台服务器进行试验,以便您在使用客户端计算机进行操作之前准确地了解必须执行的操作。


该答复似乎表明可以通过重新使用根证书密钥来更新根证书。但是我怀疑这与从头开始没有什么不同,因为新证书将具有不同的签名,因此将无法验证现有的客户端证书。
雷米·

是的,您可以延长有效期...并且比重新创建所有的pki,客户端证书和重新信任新的根目录要少工作...
ggrandes 2013年

颁发新的最终实体证书的部分不一定正确。这取决于在下级CA和最终实体证书中如何表示授权密钥标识符(AKID)。如果AKID基于{专有名称,序列号},则将实现连续性。另请参阅RFC 4518,Internet X.509公钥基础结构:认证路径构建

0

我们遇到了同样的问题,这就是我们的情况,因为Debian服务器已经过时,而openSSL出现了这个问题:

https://zh.wikipedia.org/wiki/年_2038_problem

可用于Debian 6的最新版本的OpenSSL带来了此问题。2018年1月23日之后创建的所有证书均产生有效价:1901年!

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.