証明機関のルート証明書の有効期限と更新


96

2004年に、Linux上のOpenSSLとOpenVPNで提供されるシンプルな管理スクリプトを使用して小さな認証機関を設定しました。当時見つけたガイドに従って、ルートCA証明書の有効期間を10年に設定しました。それ以来、OpenVPNトンネル、Webサイト、および電子メールサーバー用の多くの証明書に署名しました。これらすべての有効期間も10年です(これは間違っていた可能性がありますが、当時はわかりませんでした)。

CAのセットアップに関する多くのガイドを見つけましたが、その管理に関する情報はほとんどなく、特に、ルートCA証明書の有効期限が切れたときに何をする必要があるかについてはほとんど情報がありません。質問:

  • ルートCA証明書の有効期限が切れた後に有効期間が延長された証明書は、ルートCA証明書の有効期限が切れるとすぐに無効になりますか、それとも有効であり続けますか(CA証明書の有効期間中に署名されたため)?
  • ルートCA証明書を更新し、その有効期限をスムーズに移行するには、どのような操作が必要ですか?
    • 何らかの方法で現在のルートCA証明書を別の有効期間で再署名し、新しく署名した証明書をクライアントにアップロードして、クライアント証明書が有効なままになるようにすることはできますか?
    • または、すべてのクライアント証明書を、新しいルートCA証明書によって署名された新しい証明書に置き換える必要がありますか?
  • ルートCA証明書はいつ更新する必要がありますか?有効期限が近づいていますか、それとも有効期限前の妥当な時間ですか?
  • ルートCA証明書の更新が主要な作業になった場合、次の更新(もちろん、有効期間を100年に設定するのではなく)でスムーズな移行を確実にするために、今より良い方法はありますか?

一部のクライアントへの唯一のアクセスは、現在のCA証明書によって署名された証明書を使用するOpenVPNトンネルを介しているため、すべてのクライアント証明書を置換する必要がある場合、コピーする必要があるため、状況は少し複雑になります新しいファイルをクライアントに送信し、トンネルを再起動し、指を交差させて、後でファイルが表示されることを願っています。

回答:


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/

これらのディレクティブはVirtualHost443のリッスンに設定します。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は別のチェーン(古いルート)を提示しますが、自動的にそれを見つけ、信頼された(新しい)ルートに対して証明書を検証します。信頼されたルートから新しいルートを削除し、元のルート証明書を追加すると、すべてがうまくいきます。

オールドルート


だから、それだけです!更新するときに同じ秘密鍵を保持し、新しい信頼されたルートにスワップすると、ほとんどすべてが機能します。幸運を!


2
とにかく、同じ秘密鍵を再利用するだけなら、新しいルート証明書を作成する意味は何ですか?これを何度も繰り返して行うと、証明書の有効期限が切れることさえありますか?ルートの有効期限を使用して、管理者が新しい(最も強力な可能性のある)秘密キーを作成し、キーを壊そうとする進行中のマシンに対してより安全になるようにしたと思いました。20年前に作成された40ビットキーは、次の場合には十分に安全ではありません
jvhashe

2
@jvhasheルート証明書の暗号強度が十分でない場合、有効期限に関係なくルート証明書を削除する必要があります。独自のルートを生成している場合、何百年も経ってから地球上にいなくなると、それを設定することを妨げるものは何もありません。有効期限はルート証明書にはほとんど関係ありません-子証明書についても、有効期限は実際には暗号強度に関するものではありません(10月にすべての1024ビット証明書を失効させる準備をしているCAに問い合わせてください)-詳細はこちらを参照してください。
シェーンマッデン

3
上記に加えて、このメソッドが機能するにはシリアル番号が同じである必要があることがわかりました。
スコットプレスネル

2
-set_serial 01-WTF ??? シリアル番号を再利用することはできません。あなたも相談しました証明経路ビル:RFC 4158、インターネットX.509公開鍵インフラストラクチャ?それとも、あなたが進むにつれてそれを作り上げているだけですか?ユーザーがパス構築を開始するとき、ユーザーエージェントであなたが引き起こしている問題についてあなたは全く知りません。

1
@jww答えを読みましたか?これは、暗号化が機能するという事実の単なるデモンストレーションです。このコマンドは、文字通り、古いルート証明書と新しいルート証明書の関係をテストする目的で、後で検証できるテスト証明書を生成するだけです。誰かこれらのコマンドを直接使用している場合、何かが壊れることを確かに望みます。そして、盲目的にそれを実行する前に何かのコンテキストに注意を払う必要があることを認識します(または01ラボで受け入れ可能なシリアルであるかどうかについてハンドルから飛び去る)。
シェーンマッデン

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

1
出向、非常に役立つ。別の追加:受け入れられた答えに対するコメントのScott Presnellのように、更新された証明書の16進数のシリアル番号を手動で指定して、古い証明書と一致させる必要がありました。これは-set_serial 0xdeadbeefabba、後者のx509コマンドに(実際のシリアル番号:ではなく)を追加することを意味しました。その後、クライアント証明書が更新されたCA証明書に対して正常に検証されました。
JKライホ

この方法は、以前の証明書よりも同じ情報を保持するため、簡単です。
lepe

私は、このソリューションプラス-set_serialためのスクリプトを作成している-私の答えを参照
ヴォルフガングFahl

この回答により、これを必要とする問題にほぼ1日を費やした後、私は多くの作業を節約できました。
-Onitlikesonic

2

ルートの有効期間を延長する基本モード(公開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 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

ルート証明書の有効期限が切れると、それで署名した証明書も期限切れになります。新しいルート証明書を生成し、それを使用して新しい証明書に署名する必要があります。数年ごとにこのプロセスを繰り返したくない場合、唯一の本当の選択肢はルート証明書の有効期限を10年または20年のように延長することです。

ルート証明書を「更新」することはできません。できることは、新しいものを生成することだけです。

古いルートの有効期限が切れる少なくとも1〜2年前に新しいルートを生成して、問題が発生した場合にタイムウォールに逆らうことなく切り替えられるようにします。そうすれば、新しい証明書の問題が解決するまで、常に一時的に古い証明書に切り替えることができます。

VPNトンネルに関しては、テスト用のサーバーをいくつかセットアップして、クライアントマシンで実行する前に何をする必要があるかを正確に理解できるようにします。


この応答は、キーを再利用することにより、ルート証明書を更新できることを示唆しているようです。しかし、新しい証明書は異なる署名を持ち、既存のクライアント証明書を検証しないので、これは最初から始めるのと違いはないと思います。
レミーブランク

はい、あなたは...有効期間を延長し、すべてのPKI、クライアント証明書を再作成するよりも少ない仕事をされて、新しいルートをretrustすることができます...
ggrandes

新しいエンドエンティティ証明書の発行に関する部分は必ずしも真実ではありません。下位CAおよびエンドエンティティ証明書で機関キー識別子(AKID)がどのように表されるかに依存します。AKIDが{識別名、シリアル番号}に基づいている場合、連続性が達成されます。RFC 4518、インターネットX.509公開キーインフラストラクチャ:証明書パスの構築も参照してください。

0

私たちも同じ問題を抱えていましたが、これはDebianサーバーが古く、openSSLがこの問題を抱えていたためです。

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

Debian 6で利用可能なOpenSSLの最後のバージョンは、この問題をもたらします。2018年1月23日以降に作成されたすべての証明書は、Vality:1901年を生成します!

解決策は、OpenSSLを更新することです。クライアントの構成ファイル(証明書付き)を再度作成できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.