@kyanny's blog

My thoughts, my life. Views/opinions are my own.

cfssl selfsign

cfssl is CloudFlare's PKI/TLS toolkit.

github.com

openssl なり CA.sh CA.pl の代替コマンド、という位置付け。あとは証明書サーバー?にもなるらしい。

liosk.blog103.fc2.com

qiita.com

各種ファイルを 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