X509v3 Subject Key Identifier

X509証明書のv3拡張にはSubject Key Identifier (SKI)というものがある。

このSKIはそのままでX509証明書に含まれる公開鍵の識別子である。

$ openssl x509 -text -noout -in server.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 13130459247485585328 (0xb638c31e101f07b0)
    Signature Algorithm: ecdsa-with-SHA256
        Issuer: CN=root ca
        Validity
            Not Before: Aug  4 14:53:26 2020 GMT
            Not After : Aug  4 14:53:26 2021 GMT
        Subject: CN=server
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:18:76:24:20:7e:90:d5:8e:a9:76:3d:1b:0f:56:
                    01:f1:4e:6f:7f:43:71:2c:3f:86:15:45:08:03:2e:
                    d4:2d:d1:12:c9:f1:9e:4f:a6:03:dc:6b:50:ab:a7:
                    c0:4a:62:cc:0f:64:7b:00:fe:9a:d7:84:89:5b:35:
                    e4:e8:c2:50:32
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Subject Alternative Name:
                DNS:localhost
            X509v3 Subject Key Identifier:
                5B:77:97:D1:B9:03:E2:C4:31:F6:84:3F:E6:70:51:BB:86:DD:DD:87
    Signature Algorithm: ecdsa-with-SHA256
         30:46:02:21:00:e0:39:08:21:72:e8:8c:0c:65:5f:e4:34:ed:
         04:bb:69:80:75:e8:d8:05:23:33:e3:6c:27:5d:49:50:a4:45:
         72:02:21:00:af:e8:84:50:95:fc:36:6f:01:13:03:90:f2:f0:
         21:20:cc:0d:42:70:98:c4:af:6a:78:5d:ef:7f:cf:d8:d3:a8

このSKIはopensslコマンドを使用する場合、証明書署名時に以下のような設定のextfileをオプションで与えると書き込まれる

subjectKeyIdentifier = hash

そしてこのhash、ただ公開鍵のハッシュを求めるのかと思ったら違った。。。

OpenSSLの説明(x509v3_config)を見ると2つの設定があるらしい。

  • hashが設定されていたらRFC5258に従って計算したハッシュ値が入る
  • 他の設定(違う文字列?)なら16進の文字列が入る(非推奨)

とのこと

そしてRFC5258には公開鍵からSKIを求める方法は一般的に2つあると書いてある

  • 1つは公開鍵のBIT STRING(excluding the tag, length and number of unused bits)のSHA1ハッシュ
  • もう1つは4bitのタイプフィールドとそれに続く公開鍵のBIT STRINGのSHA1ハッシュの最下位60bit

らしいが、

あくまで一般的な方法の例なので、ユニークな識別子を生成できるなら他の方法でも良い。

ここでopensslのhashという設定は前者になる模様

そんでもってここで言うBIT STRINGとは公開鍵ファイルからタグや長さ等のメタ情報を除いたもの。

これはopensslのasn1parseで求めることができる。

  1. まずパースして構造をチェック
    $ openssl asn1parse -in pub.key
        0:d=0  hl=2 l=  89 cons: SEQUENCE
        2:d=1  hl=2 l=  19 cons: SEQUENCE
        4:d=2  hl=2 l=   7 prim: OBJECT            :id-ecPublicKey
       13:d=2  hl=2 l=   8 prim: OBJECT            :prime256v1
       23:d=1  hl=2 l=  66 prim: BIT STRING
    ここでは23がBIT STRINGのオフセットである(オフセットは鍵のアルゴリズムによって変わる)
  2. BIT STRINGのオフセットを設定してパース
    $ openssl asn1parse -in pub.key -strparse 23 -noout -out pub.bin


これでBIT STRINGが求められたのであとはハッシュ(SHA1)の計算をするだけ

$ openssl sha1 pub.bin
SHA1(pub.bin)= 5b7797d1b903e2c431f6843fe67051bb86dddd87


↓ 証明書のSKI(再掲)

X509v3 Subject Key Identifier:
                5B:77:97:D1:B9:03:E2:C4:31:F6:84:3F:E6:70:51:BB:86:DD:DD:87


ちょっと表現が違いますが、見比べてみると全く同じSHA1の160bitのハッシュ値ですねヽ(・∀・)ノ ワチョーイ♪

コメントする