證書頒發機構根證書到期和續訂
2004 年,我在 Linux 上使用 OpenSSL 和 OpenVPN 提供的簡單管理腳本建立了一個小型證書頒發機構。按照我當時找到的指南,我將根 CA 證書的有效期設置為 10 年。從那時起,我為 OpenVPN 隧道、網站和電子郵件伺服器簽署了許多證書,所有這些證書也都有 10 年的有效期(這可能是錯誤的,但我當時並不知道更好)。
我找到了很多關於設置 CA 的指南,但關於其管理的資訊很少,特別是關於根 CA 證書到期時必須做的事情,這將在 2014 年的某個時間發生。所以我有以下問題:
在根 CA 證書到期後延長有效期的證書會在根 CA 證書到期後立即失效,還是繼續有效(因為它們是在 CA 證書的有效期內簽署的)?
需要哪些操作來更新根 CA 證書並確保在其到期期間順利過渡?
- 我可以以某種方式重新簽署具有不同有效期的目前根 CA 證書,並將新簽署的證書上傳到客戶端,以便客戶端證書保持有效嗎?
- 還是我需要用新的根 CA 證書籤名的新證書替換所有客戶端證書?
什麼時候應該更新根 CA 證書?接近到期日,還是到期前的合理時間?
如果根 CA 證書的更新成為一項主要工作,我現在可以做些什麼來確保在下一次更新時更順利地過渡(當然,沒有將有效期設置為 100 年)?
由於我對某些客戶端的唯一訪問是通過使用由目前 CA 證書籤名的證書的 OpenVPN 隧道,因此情況稍微複雜一些,因此如果我必須替換所有客戶端證書,我將需要複製將新文件發送到客戶端,重新啟動隧道,交叉手指,希望之後會出現。
在根 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 加密 API 瀏覽器,Apache 會顯示舊根,但新根仍然在電腦的受信任根儲存中。儘管 Apache 提供了不同的鏈(舊根),但它會自動找到它並針對受信任的(新)根驗證證書。從受信任的根中剝離新根並添加原始根證書後,一切都很好:
就是這樣了!更新時保持相同的私鑰,換入新的受信任的根,它幾乎都可以正常工作。祝你好運!