cfssl
is CloudFlare's PKI/TLS toolkit.
openssl
なり CA.sh
CA.pl
の代替コマンド、という位置付け。あとは証明書サーバー?にもなるらしい。
各種ファイルを JSON 形式で表現する。この JSON の syntax リファレンスが(README.md にサンプルは書いてあるものの)不明で使い方がわからん、と思ったが print-defaults
コマンドで雛形を作って適宜編集して使う、というもののようだ。
selfsign
サブコマンドで自己署名証明書を作ってみる。
❯ cfssl print-defaults csr | tee csr.json { "CN": "example.net", "hosts": [ "example.net", "www.example.net" ], "key": { "algo": "ecdsa", "size": 256 }, "names": [ { "C": "US", "ST": "CA", "L": "San Francisco" } ] } ❯ cfssl selfsign example.com csr.json | tee cert.json 2023/10/16 12:41:57 [INFO] generate received request 2023/10/16 12:41:57 [INFO] received CSR 2023/10/16 12:41:57 [INFO] generating key: ecdsa-256 2023/10/16 12:41:57 [INFO] encoded CSR *** WARNING *** Self-signed certificates are dangerous. Use this self-signed certificate at your own risk. It is strongly recommended that these certificates NOT be used in production. *** WARNING *** {"cert":"-----BEGIN CERTIFICATE-----\nMIICDzCCAbWgAwIBAgIIbf+wpkgJXUwwCgYIKoZIzj0EAwIwSDELMAkGA1UEBhMC\nVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRQwEgYDVQQD\nEwtleGFtcGxlLm5ldDAeFw0yMzEwMTYwMzM2NTdaFw0yNDAxMTUwOTQxNTdaMEgx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEUMBIGA1UEAxMLZXhhbXBsZS5uZXQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC\nAARBtN40okpotQNeix9ZDZDUrSmaK8fs039Nb3U7DaRXaDv5YzTmGfzmhUuQhTwT\neYTKT/f7gG7YoaGzf4WtsQ0Jo4GIMIGFMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUE\nFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU\n6t1+02wYfSzNFD4w9A6Br/q8+egwJwYDVR0RBCAwHoILZXhhbXBsZS5uZXSCD3d3\ndy5leGFtcGxlLm5ldDAKBggqhkjOPQQDAgNIADBFAiEA9q81kBp/j8AMxxZlORhL\nfKBOj3eJP+QQWb8e8goKXGECICxGw+MmQHd/sPyZ+MoPHjH+I6GJPP1sSeFvaSZa\nRgEc\n-----END CERTIFICATE-----\n","csr":"-----BEGIN CERTIFICATE REQUEST-----\nMIIBPDCB5AIBADBIMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcT\nDVNhbiBGcmFuY2lzY28xFDASBgNVBAMTC2V4YW1wbGUubmV0MFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAEQbTeNKJKaLUDXosfWQ2Q1K0pmivH7NN/TW91Ow2kV2g7\n+WM05hn85oVLkIU8E3mEyk/3+4Bu2KGhs3+FrbENCaA6MDgGCSqGSIb3DQEJDjEr\nMCkwJwYDVR0RBCAwHoILZXhhbXBsZS5uZXSCD3d3dy5leGFtcGxlLm5ldDAKBggq\nhkjOPQQDAgNHADBEAiA2NjDwqlSikvk7txHNfJbNp8X28+QjSFhiAJEvwKXcSQIg\nL1sTEKohQRpKqe5hSDhlgP94xaPJFQsauFKwU6Saiiw=\n-----END CERTIFICATE REQUEST-----\n","key":"-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIAEIP6D7JWYlBTcC21YvTyflu+aW/XAvDsEgRcfwppieoAoGCCqGSM49\nAwEHoUQDQgAEQbTeNKJKaLUDXosfWQ2Q1K0pmivH7NN/TW91Ow2kV2g7+WM05hn8\n5oVLkIU8E3mEyk/3+4Bu2KGhs3+FrbENCQ==\n-----END EC PRIVATE KEY-----\n"} ❯ jq . cert.json { "cert": "-----BEGIN CERTIFICATE-----\nMIICDzCCAbWgAwIBAgIIbf+wpkgJXUwwCgYIKoZIzj0EAwIwSDELMAkGA1UEBhMC\nVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRQwEgYDVQQD\nEwtleGFtcGxlLm5ldDAeFw0yMzEwMTYwMzM2NTdaFw0yNDAxMTUwOTQxNTdaMEgx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEUMBIGA1UEAxMLZXhhbXBsZS5uZXQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC\nAARBtN40okpotQNeix9ZDZDUrSmaK8fs039Nb3U7DaRXaDv5YzTmGfzmhUuQhTwT\neYTKT/f7gG7YoaGzf4WtsQ0Jo4GIMIGFMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUE\nFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU\n6t1+02wYfSzNFD4w9A6Br/q8+egwJwYDVR0RBCAwHoILZXhhbXBsZS5uZXSCD3d3\ndy5leGFtcGxlLm5ldDAKBggqhkjOPQQDAgNIADBFAiEA9q81kBp/j8AMxxZlORhL\nfKBOj3eJP+QQWb8e8goKXGECICxGw+MmQHd/sPyZ+MoPHjH+I6GJPP1sSeFvaSZa\nRgEc\n-----END CERTIFICATE-----\n", "csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIIBPDCB5AIBADBIMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcT\nDVNhbiBGcmFuY2lzY28xFDASBgNVBAMTC2V4YW1wbGUubmV0MFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAEQbTeNKJKaLUDXosfWQ2Q1K0pmivH7NN/TW91Ow2kV2g7\n+WM05hn85oVLkIU8E3mEyk/3+4Bu2KGhs3+FrbENCaA6MDgGCSqGSIb3DQEJDjEr\nMCkwJwYDVR0RBCAwHoILZXhhbXBsZS5uZXSCD3d3dy5leGFtcGxlLm5ldDAKBggq\nhkjOPQQDAgNHADBEAiA2NjDwqlSikvk7txHNfJbNp8X28+QjSFhiAJEvwKXcSQIg\nL1sTEKohQRpKqe5hSDhlgP94xaPJFQsauFKwU6Saiiw=\n-----END CERTIFICATE REQUEST-----\n", "key": "-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIAEIP6D7JWYlBTcC21YvTyflu+aW/XAvDsEgRcfwppieoAoGCCqGSM49\nAwEHoUQDQgAEQbTeNKJKaLUDXosfWQ2Q1K0pmivH7NN/TW91Ow2kV2g7+WM05hn8\n5oVLkIU8E3mEyk/3+4Bu2KGhs3+FrbENCQ==\n-----END EC PRIVATE KEY-----\n" }
certinfo
サブコマンドで、証明書ファイルの情報を JSON 形式で表示できる。プログラムから扱うときは openssl x509
の出力よりパースしやすくて便利そう。というか、あの情報はこうやって構造化するといいんだな、というお手本になる。まあすでにこの形式(とツール)があるので、もはや自分で独自フォーマットの構造化をする必要はないわけだが。
❯ jq -r .cert cert.json > server.crt ❯ cfssl certinfo -cert server.crt { "subject": { "common_name": "example.net", "country": "US", "locality": "San Francisco", "province": "CA", "names": [ "US", "CA", "San Francisco", "example.net" ] }, "issuer": { "common_name": "example.net", "country": "US", "locality": "San Francisco", "province": "CA", "names": [ "US", "CA", "San Francisco", "example.net" ] }, "serial_number": "7926248097414995276", "sans": [ "example.net", "www.example.net" ], "not_before": "2023-10-16T03:36:57Z", "not_after": "2024-01-15T09:41:57Z", "sigalg": "ECDSAWithSHA256", "authority_key_id": "", "subject_key_id": "EA:DD:7E:D3:6C:18:7D:2C:CD:14:3E:30:F4:0E:81:AF:FA:BC:F9:E8", "pem": "-----BEGIN CERTIFICATE-----\nMIICDzCCAbWgAwIBAgIIbf+wpkgJXUwwCgYIKoZIzj0EAwIwSDELMAkGA1UEBhMC\nVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRQwEgYDVQQD\nEwtleGFtcGxlLm5ldDAeFw0yMzEwMTYwMzM2NTdaFw0yNDAxMTUwOTQxNTdaMEgx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\nbzEUMBIGA1UEAxMLZXhhbXBsZS5uZXQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC\nAARBtN40okpotQNeix9ZDZDUrSmaK8fs039Nb3U7DaRXaDv5YzTmGfzmhUuQhTwT\neYTKT/f7gG7YoaGzf4WtsQ0Jo4GIMIGFMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUE\nFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU\n6t1+02wYfSzNFD4w9A6Br/q8+egwJwYDVR0RBCAwHoILZXhhbXBsZS5uZXSCD3d3\ndy5leGFtcGxlLm5ldDAKBggqhkjOPQQDAgNIADBFAiEA9q81kBp/j8AMxxZlORhL\nfKBOj3eJP+QQWb8e8goKXGECICxGw+MmQHd/sPyZ+MoPHjH+I6GJPP1sSeFvaSZa\nRgEc\n-----END CERTIFICATE-----\n" }
ちゃんとした証明書が発行されている。
❯ openssl x509 -in server.crt -text -noout Certificate: Data: Version: 3 (0x2) Serial Number: 7926248097414995276 (0x6dffb0a648095d4c) Signature Algorithm: ecdsa-with-SHA256 Issuer: C = US, ST = CA, L = San Francisco, CN = example.net Validity Not Before: Oct 16 03:36:57 2023 GMT Not After : Jan 15 09:41:57 2024 GMT Subject: C = US, ST = CA, L = San Francisco, CN = example.net Subject Public Key Info: Public Key Algorithm: id-ecPublicKey Public-Key: (256 bit) pub: 04:41:b4:de:34:a2:4a:68:b5:03:5e:8b:1f:59:0d: 90:d4:ad:29:9a:2b:c7:ec:d3:7f:4d:6f:75:3b:0d: a4:57:68:3b:f9:63:34:e6:19:fc:e6:85:4b:90:85: 3c:13:79:84:ca:4f:f7:fb:80:6e:d8:a1:a1:b3:7f: 85:ad:b1:0d:09 ASN1 OID: prime256v1 NIST CURVE: P-256 X509v3 extensions: X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication X509v3 Basic Constraints: critical CA:FALSE X509v3 Subject Key Identifier: EA:DD:7E:D3:6C:18:7D:2C:CD:14:3E:30:F4:0E:81:AF:FA:BC:F9:E8 X509v3 Subject Alternative Name: DNS:example.net, DNS:www.example.net Signature Algorithm: ecdsa-with-SHA256 Signature Value: 30:45:02:21:00:f6:af:35:90:1a:7f:8f:c0:0c:c7:16:65:39: 18:4b:7c:a0:4e:8f:77:89:3f:e4:10:59:bf:1e:f2:0a:0a:5c: 61:02:20:2c:46:c3:e3:26:40:77:7f:b0:fc:99:f8:ca:0f:1e: 31:fe:23:a1:89:3c:fd:6c:49:e1:6f:69:26:5a:46:01:1c