OPENSSL: 証明書更新

OpenVPNやローカルサーバで使用するために自己証明書の認証局を作っている場合に、CA証明書を更新する方法をメモする。手順を検討するうえで、次サイトの図が参考になりました。感謝。
SSL 認証 の仕組みと OpenVPN の認証の仕組み | レンタルサーバー・自宅サーバー設定・構築のヒント (server-setting.info)

1. easy-rsaによる証明書発行例

今回はeasy-rsaで発行したCA証明書、Server証明書の更新を更新を行うケースを考えたい。このため、サンプルの証明書を次手順で作成した。

$ git clone https://github.com/OpenVPN/easy-rsa.git
$ ls easy-rsa/easyrsa3/
easyrsa  openssl-easyrsa.cnf  vars.example  x509-types
$ ./easy-rsa/easyrsa3/easyrsa init-pki
$ ls
easy-rsa  pki
$ ./easy-rsa/easyrsa3/easyrsa build-ca nopass
[...]
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:CA1
[...]
$
$ ls ./pki/ca.crt
./pki/ca.crt
$ ls ./pki/private/ca.key
./pki/private/ca.key
$ ./easy-rsa/easyrsa3/easyrsa gen-req myserver.example.com nopass
[...]
Common Name (eg: your user, host, or server name) [myserver.example.com]:
[...]
* req: ./pki/reqs/myserver.example.com.req
* key: ./pki/private/myserver.example.com.key
$
$ ./easy-rsa/easyrsa3/easyrsa sign-req server myserver.example.com
[...]
  Confirm request details: yes
[...]
Certificate created at:
* ./pki/issued/myserver.example.com.crt
$
$ ls ./pki/private/myserver.example.com.key
./pki/private/myserver.example.com.key
$ ls ./pki/issued/myserver.example.com.crt
./pki/issued/myserver.example.com.crt
$
$ openssl verify -CAfile ./pki/ca.crt -verbose ./pki/issued/myserver.example.com.crt
./pki/issued/myserver.example.com.crt: OK

2. CA証明書の更新

CA証明書の更新を行う。CA証明書の更新は認証局の再作成で行う例が多い気がするが、OpenVPNなどではClient証明書の再発行も必要になってしまう。今回は再発行したCA証明書が発行済みのClient証明書を復号できるようにしたい。そのために、新しく作成するCA証明書は既存のCA証明書の内容を極力踏襲したCA証明書を作成する。

まずは既存のCA証明書(ca.crt)のSerial NumberとX509v3 extensionsを確認する。なお、発行済みの証明書、鍵についてはあらかじめ作業ディレクトリにコピーしておく。

$ ls
ca.crt  ca.key  myserver.example.com.crt  myserver.example.com.key
$
$ openssl x509 -noout -text -in ./ca.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            7e:f2:58:6b:42:91:0f:6a:97:61:82:d8:15:ed:5f:a4:d1:76:e5:96
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN = CA1
        Validity
            Not Before: Mar 19 06:08:59 2024 GMT
            Not After : Mar 17 06:08:59 2034 GMT
        Subject: CN = CA1
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:92:5d:f3:49:ff:cf:34:b3:56:bc:80:9b:68:5d:
                    69:18:c4:b5:30:37:99:c8:aa:7c:b2:63:9f:0b:5e:
                    f4:b6:3e:4b:8d:1c:01:44:5e:a8:21:70:1b:1a:16:
                    af:c2:d4:39:4a:a6:3b:14:4b:71:4d:b2:6c:8d:bb:
                    bd:19:73:53:ca:89:e8:46:13:19:39:56:1b:0c:bb:
                    78:fa:9d:91:45:a5:c8:09:0d:43:06:5f:31:51:13:
                    52:c8:bf:e1:33:be:fb:b1:42:dc:68:b5:34:14:d8:
                    8a:00:68:db:be:51:c0:66:f7:87:0c:4b:09:6c:c9:
                    a6:d3:e6:e6:49:d7:f4:7a:bd:ac:44:d1:20:8c:b1:
                    93:80:08:a6:a2:44:53:a4:93:83:57:ac:70:82:3c:
                    3e:62:61:34:7b:b1:02:da:4f:b7:4a:fb:95:6e:5f:
                    8f:df:8a:e3:c2:c1:99:4e:56:1d:34:b5:da:36:87:
                    cc:62:2a:36:02:9d:a6:86:1c:88:26:c5:a9:85:6a:
                    8b:e8:2f:f9:4a:61:21:08:57:d2:04:1d:d7:47:ec:
                    ac:b0:84:7d:b4:82:5d:26:2a:4c:fd:1f:2e:1b:de:
                    fb:7b:82:0f:1a:11:40:71:b4:2d:32:45:28:f1:e2:
                    69:af:80:d9:7b:36:75:c0:81:f2:0e:ed:ad:27:87:
                    a4:a7
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:TRUE
            X509v3 Subject Key Identifier:
                DA:7C:AA:A7:41:93:51:E2:82:9D:E7:81:3C:88:CE:21:8F:DA:8E:84
            X509v3 Authority Key Identifier:
                keyid:DA:7C:AA:A7:41:93:51:E2:82:9D:E7:81:3C:88:CE:21:8F:DA:8E:84
                DirName:/CN=CA1
                serial:7E:F2:58:6B:42:91:0F:6A:97:61:82:D8:15:ED:5F:A4:D1:76:E5:96
            X509v3 Key Usage:
                Certificate Sign, CRL Sign
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:(省略)

既存CA証明書のX509v3 extensionsに対応する形でca_v3.txtを用意する。

basicConstraints=CA:TRUE
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
keyUsage=cRLSign,keyCertSign

既存のCA証明書からCA証明書要求を作成する。CNを変えることもできるが、CN変えると発行済みのclient証明書のIssuerから変わってしまうので今回は変更をしない

$ openssl x509 -x509toreq -in ./ca.crt -signkey ./ca.key -out ca_new.csr
※ subjectを変えたい場合は -subj "/CN=CA2"などとコマンドに追加する

CA証明書要求から新しいCA証明書を作成する。

$ openssl x509 -req -days 36500 \
    -in ca_new.csr \
    -signkey ./ca.key \
    -out ca_new.crt \
    -extfile ca_v3.txt \
    -set_serial 0x7ef2586b42910f6a976182d815ed5fa4d176e596

Certificate request self-signature ok
subject=CN = CA1
$ openssl x509 -noout -text -in ./ca_new.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            7e:f2:58:6b:42:91:0f:6a:97:61:82:d8:15:ed:5f:a4:d1:76:e5:96
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN = CA1
        Validity
            Not Before: Mar 19 11:37:20 2024 GMT
            Not After : Feb 24 11:37:20 2124 GMT
        Subject: CN = CA1
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:92:5d:f3:49:ff:cf:34:b3:56:bc:80:9b:68:5d:
                    69:18:c4:b5:30:37:99:c8:aa:7c:b2:63:9f:0b:5e:
                    f4:b6:3e:4b:8d:1c:01:44:5e:a8:21:70:1b:1a:16:
                    af:c2:d4:39:4a:a6:3b:14:4b:71:4d:b2:6c:8d:bb:
                    bd:19:73:53:ca:89:e8:46:13:19:39:56:1b:0c:bb:
                    78:fa:9d:91:45:a5:c8:09:0d:43:06:5f:31:51:13:
                    52:c8:bf:e1:33:be:fb:b1:42:dc:68:b5:34:14:d8:
                    8a:00:68:db:be:51:c0:66:f7:87:0c:4b:09:6c:c9:
                    a6:d3:e6:e6:49:d7:f4:7a:bd:ac:44:d1:20:8c:b1:
                    93:80:08:a6:a2:44:53:a4:93:83:57:ac:70:82:3c:
                    3e:62:61:34:7b:b1:02:da:4f:b7:4a:fb:95:6e:5f:
                    8f:df:8a:e3:c2:c1:99:4e:56:1d:34:b5:da:36:87:
                    cc:62:2a:36:02:9d:a6:86:1c:88:26:c5:a9:85:6a:
                    8b:e8:2f:f9:4a:61:21:08:57:d2:04:1d:d7:47:ec:
                    ac:b0:84:7d:b4:82:5d:26:2a:4c:fd:1f:2e:1b:de:
                    fb:7b:82:0f:1a:11:40:71:b4:2d:32:45:28:f1:e2:
                    69:af:80:d9:7b:36:75:c0:81:f2:0e:ed:ad:27:87:
                    a4:a7
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:TRUE
            X509v3 Subject Key Identifier:
                DA:7C:AA:A7:41:93:51:E2:82:9D:E7:81:3C:88:CE:21:8F:DA:8E:84
            X509v3 Authority Key Identifier:
                keyid:DA:7C:AA:A7:41:93:51:E2:82:9D:E7:81:3C:88:CE:21:8F:DA:8E:84
                DirName:/CN=CA1
                serial:7E:F2:58:6B:42:91:0F:6A:97:61:82:D8:15:ED:5F:A4:D1:76:E5:96
            X509v3 Key Usage:
                Certificate Sign, CRL Sign
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:(省略)

今回の手順では証明書の有効期限(Validity)と署名(Signature Value)以外は同じ内容で発行することが出来ている。発行済みのサーバ証明書が新旧どちらのCA証明書でも検証できることを確認する。

$ openssl verify -CAfile ./ca.crt -verbose ./myserver.example.com.crt
./myserver.example.com.crt: OK
$ openssl verify -CAfile ./ca_new.crt -verbose ./myserver.example.com.crt
./myserver.example.com.crt: OK

※Serial Numberを合わせなくてもverifyはOKになるようだ。ただし、OpenVPNのClientからはCAの不一致が検出された。
 Serial Numberもきちんと合わせておいた方がよい。

3. Server証明書の更新

次はServer証明書の更新を行う。 (※Client証明書も更新方法は大体で同じで、v3.txtの内容が違うぐらいのはず)
CA証明書と違って、Server証明書やClient証明書にはeasy-rsaで更新コマンドが用意されているようなのでそちらを利用してもよいが、今回はCA証明書と同じようにopensslコマンドで更新版を作成する。

Server証明書はCommonNameを変えてmyserver2.example.comとして更新を行う(同じでも良い)。発行済みのmyserver.example.com.crtのSerial NumberとX509v3 extensionsを確認する。

$ openssl x509 -noout -text -in ./myserver.example.com.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            3b:74:70:e1:5d:ad:95:9e:1d:23:e2:39:28:e6:0c:ae
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN = CA1
        Validity
            Not Before: Mar 19 06:13:34 2024 GMT
            Not After : Jun 22 06:13:34 2026 GMT
        Subject: CN = myserver.example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:96:96:02:09:2c:a4:ef:fc:f7:5e:f1:ba:14:7e:
                    4e:3f:b3:67:20:82:85:29:37:8e:03:c5:60:96:97:
                    6f:67:f1:09:26:75:72:71:d6:41:fd:ee:51:fc:26:
                    97:26:a0:88:69:cc:c6:8f:79:c0:76:47:02:88:4e:
                    20:9d:91:70:31:93:07:cf:d5:f0:d6:81:fa:e6:ee:
                    9f:c9:7f:e2:f0:b5:50:10:04:63:d5:0c:65:5d:27:
                    63:a7:21:fc:ec:a6:0c:7a:74:1e:8d:12:18:68:29:
                    76:c5:65:67:9b:f9:c6:7a:f6:64:7e:b8:59:a1:84:
                    5b:6b:5d:f1:d3:2c:b4:b7:9a:03:21:a5:5f:8e:40:
                    52:f5:33:0b:62:3f:de:26:09:bd:70:22:37:5b:45:
                    12:ed:82:a9:75:6e:80:f8:2c:8b:99:93:c0:2e:14:
                    cd:05:45:a0:b2:06:be:21:b9:93:89:b4:95:a3:38:
                    1e:c0:be:1b:2a:73:db:e5:0e:4e:33:52:3c:53:44:
                    61:c8:34:4c:ad:69:16:98:14:f8:f4:8a:10:37:4e:
                    f2:e9:ef:aa:2c:c4:aa:d3:10:b5:11:fa:72:28:c5:
                    47:cd:b8:04:07:d8:d6:85:3e:c8:2d:e1:09:b0:12:
                    46:a4:0d:a2:0f:52:32:61:1e:1d:d6:55:f7:b5:8d:
                    a8:ff
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Subject Key Identifier:
                95:61:BA:77:06:83:66:62:DD:F6:2C:D3:63:02:3A:66:4A:6F:C3:93
            X509v3 Authority Key Identifier:
                keyid:DA:7C:AA:A7:41:93:51:E2:82:9D:E7:81:3C:88:CE:21:8F:DA:8E:84
                DirName:/CN=CA1
                serial:7E:F2:58:6B:42:91:0F:6A:97:61:82:D8:15:ED:5F:A4:D1:76:E5:96
            X509v3 Extended Key Usage:
                TLS Web Server Authentication
            X509v3 Key Usage:
                Digital Signature, Key Encipherment
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:(省略)

X509v3 extensionsの内容からserver_v3.txtを作成する

basicConstraints=CA:FALSE
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
extendedKeyUsage = serverAuth
keyUsage=digitalSignature, keyEncipherment

Server証明書要求を作成する。今回はCNを変更してみる。

$ openssl x509 -x509toreq -in ./myserver.example.com.crt \
    -signkey ./myserver.example.com.key \
    -out ./myserver2.example.com.csr \
    -subj "/CN=myserver2.example.com"

Server証明書を作成する。

$ openssl x509 -req -days 36500 \
    -in myserver2.example.com.csr \
    -CA ./ca_new.crt \
    -CAkey ./ca.key \
    -out myserver2.example.com.crt \
    -extfile v3_server.txt \
    -set_serial 0x3b7470e15dad959e1d23e23928e60cae

Certificate request self-signature ok
subject=CN = myserver2.example.com

$ ls
ca.crt  ca_new.crt  ca_v3.txt                 myserver.example.com.key   myserver2.example.com.csr
ca.key  ca_new.csr  myserver.example.com.crt  myserver2.example.com.crt  v3_server.txt

作成したServer証明書を確認する。

$ openssl x509 -noout -text -in ./myserver2.example.com.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            3b:74:70:e1:5d:ad:95:9e:1d:23:e2:39:28:e6:0c:ae
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN = CA1
        Validity
            Not Before: Mar 19 12:00:47 2024 GMT
            Not After : Feb 24 12:00:47 2124 GMT
        Subject: CN = myserver2.example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:96:96:02:09:2c:a4:ef:fc:f7:5e:f1:ba:14:7e:
                    4e:3f:b3:67:20:82:85:29:37:8e:03:c5:60:96:97:
                    6f:67:f1:09:26:75:72:71:d6:41:fd:ee:51:fc:26:
                    97:26:a0:88:69:cc:c6:8f:79:c0:76:47:02:88:4e:
                    20:9d:91:70:31:93:07:cf:d5:f0:d6:81:fa:e6:ee:
                    9f:c9:7f:e2:f0:b5:50:10:04:63:d5:0c:65:5d:27:
                    63:a7:21:fc:ec:a6:0c:7a:74:1e:8d:12:18:68:29:
                    76:c5:65:67:9b:f9:c6:7a:f6:64:7e:b8:59:a1:84:
                    5b:6b:5d:f1:d3:2c:b4:b7:9a:03:21:a5:5f:8e:40:
                    52:f5:33:0b:62:3f:de:26:09:bd:70:22:37:5b:45:
                    12:ed:82:a9:75:6e:80:f8:2c:8b:99:93:c0:2e:14:
                    cd:05:45:a0:b2:06:be:21:b9:93:89:b4:95:a3:38:
                    1e:c0:be:1b:2a:73:db:e5:0e:4e:33:52:3c:53:44:
                    61:c8:34:4c:ad:69:16:98:14:f8:f4:8a:10:37:4e:
                    f2:e9:ef:aa:2c:c4:aa:d3:10:b5:11:fa:72:28:c5:
                    47:cd:b8:04:07:d8:d6:85:3e:c8:2d:e1:09:b0:12:
                    46:a4:0d:a2:0f:52:32:61:1e:1d:d6:55:f7:b5:8d:
                    a8:ff
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            X509v3 Subject Key Identifier:
                95:61:BA:77:06:83:66:62:DD:F6:2C:D3:63:02:3A:66:4A:6F:C3:93
            X509v3 Authority Key Identifier:
                keyid:DA:7C:AA:A7:41:93:51:E2:82:9D:E7:81:3C:88:CE:21:8F:DA:8E:84
                DirName:/CN=CA1
                serial:7E:F2:58:6B:42:91:0F:6A:97:61:82:D8:15:ED:5F:A4:D1:76:E5:96
            X509v3 Extended Key Usage:
                TLS Web Server Authentication
            X509v3 Key Usage:
                Digital Signature, Key Encipherment
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:(省略)

CA証明書と同様に証明書の有効期限(Validity)と署名(Signature Value)以外は同じ内容で発行することが出来ている(Subject: CN = myserver2.example.comの変更は意図的なもの)。発行済みのサーバ証明書が新旧どちらのCA証明書でも検証できることを確認する。

$ openssl verify -verbose -CAfile ./ca.crt ./myserver2.example.com.crt
./myserver2.example.com.crt: OK
$ openssl verify -verbose -CAfile ./ca_new.crt ./myserver2.example.com.crt
./myserver2.example.com.crt: OK

これでClient側が古いca.crtを使っていても期限が切れるまでは使い続けることが出来る(少なくとも2024年3月時点で最新のopenvpnであれば……)。

認証局を再作成する場合は古いca.crtで新しいServer証明書を復号できず、新しいca.crtで発行済みのClient証明書を復号できないので、ServerとClientの更新を同時に行う必要がある。今回はServerとClientの更新を非同期で行うことが許容される。