Skip to content
nishi_74322014 edited this page Sep 1, 2026 · 1 revision

JWK

概要

以下の内容で最終確認済み。
https://tools.ietf.org/html/rfc7517

  • JWK : JSON Web Key は、

    • JWSJWEなどで利用する公開鍵を
      JSON 形式で表現するための仕様。
      FIDO2Web Authentication API が生成する
      公開鍵なども、JWK で表現されている。

    • 複数の JWK のセットである JWK Set JSON データ構造も定義する。
      OpenID Connect Discovery をサポートしている IdP は
      公開鍵を JWK Set 形式で公開していることが多い。

  • 暗号アルゴリズムおよびその識別子は、JWA の RFC(JWA)に記載。

JSON Web Key (JWK)

  • 暗号鍵を表現する JSON オブジェクト。
  • このオブジェクトの各要素は、鍵の各プロパティを表現する。

JWK Set

  • 1 セットの JWK の集合を表現する JSON オブジェクト。
  • この JSON オブジェクトは必ず keys という要素を含み、
    その要素は JWK の配列となる。

補足(運用の要): JWK Set の実運用上の意味は「鍵のロールオーバー」にある。

IdP は新旧 2 つの鍵を jwks_uri同時に並べておき、
新しい鍵で署名を始める。RP 側は kid で該当する鍵を選ぶため、
切り替えの瞬間にトークンが検証できなくなる事故を避けられる。

RP 側の注意点は次の通り。

  • jwks_uriキャッシュする(毎回取りに行かない)が、
    未知の kid を見たら再取得する(ただしレート制限を掛ける)。
  • 取得先は openid-configuration から得た URL に固定し、
    トークンのヘッダ(jku)で指定させない。

詳細

パラメタ(JWK)

一覧

# キー 説明
1 kty(必須) key type パラメタ。大文字・小文字を区別する。RSA や EC といった暗号アルゴリズムファミリを示す。
2 alg(任意) algorithm パラメタ。大文字・小文字を区別する ASCII 文字列。鍵で利用されるアルゴリズムを示す。
3 kid(任意) Key ID パラメタ。大文字・小文字を区別するが、値の構造は未定義。鍵のロールオーバー時に JWK Set の中から必要な鍵を特定するなど、特定の鍵を識別するために用いられる。JWSJWE とともに利用する場合、Header に含まれる kid 値と一致させる。kid の生成には、JWK Thumbprint(RFC 7638)という仕様が使用されることが多い。
4 use(任意) public key use パラメタ。大文字・小文字を区別する。当該公開鍵の用途を示す。署名検証目的(sig)or 暗号化目的(enc
5 key_ops(任意) key operations パラメタ。大文字・小文字を区別する。公開鍵, 暗号鍵, 共通鍵のいずれのユースケースを想定した鍵のオペレーションを示す。
6 x5u(任意) X.509 URL パラメタ。X.509 公開鍵証明書や証明書チェーンといったリソースを指し示す URI。リソースは、PEM エンコード形式で、チェーンの先頭の証明書と一致させ、HTTPS の GET で取得する。
7 x5c(任意) X.509 certificate chain パラメタ。PKIX 証明書(base64 エンコードされた DER 形式)の JSON 配列。配列の先頭は、チェーンの先頭の PKIX 証明書で、その後に証明書を続けることもできる。
8 x5t(任意) X.509 Certificate SHA-1 Thumbprint パラメタ。DER エンコードされた X.509 証明書の SHA-1 thumbprint (a.k.a. digest) の base64url エンコード値。
9 x5t#S256(任意) X.509 Certificate SHA-256 Thumbprint パラメタ。DER エンコードされた X.509 証明書の SHA-256 thumbprint (a.k.a. digest) の base64url エンコード値。

移行メモ(正誤): 元ページの use の説明は
「暗号化目的 (sig) or 署名検証目的 (enc)」と逆になっていたので正した。
RFC 7517 の定義は次の通り。

用途
sig signature(署名・検証)
enc encryption(暗号化・鍵の受け渡し)

alg

JWSJWE用の alg は JWA の RFC(JWA)を参照。

use と key_ops

  • usekey_ops は同時に利用すべきではない。
  • key_ops
# 説明
1 sign compute digital signature or MAC
2 verify verify digital signature or MAC
3 encrypt encrypt content
4 decrypt decrypt content and validate decryption, if applicable
5 wrapKey encrypt key
6 unwrapKey decrypt key and validate decryption, if applicable
7 deriveKey derive key
8 deriveBits derive bits not to be used as a key

kty と kid

異なる鍵が同じ kid 値を持つケースがある。

kty は異なるが, アプリケーションからはそれらが
互いに等価な代替手段であると考えられている場合。

JWK Thumbprint

kid の値の決め方は仕様上自由だが、
**RFC 7638(JWK Thumbprint)**で決定的に導出するのが一般的である。

  • 鍵種別ごとの必須メンバのみを取り出し、
  • 辞書順・空白なしの JSON に正規化し、
  • SHA-256 を取って base64url エンコードする。

同じ鍵からは常に同じ kid が得られるため、
発行側と検証側で kid の付け方を調整する必要がなくなる。

パラメタ(JWA)

パラメタ(JWK) に含まれないパラメタは、
JWA の RFC で、アルゴリズム毎に定義されているパラメタになる。

Parameters for Symmetric Keys

kty = oct の場合(、合わせて、alg も必要)、
k に base64url エンコードされた Symmetric Keys を保存する。

Parameters for RSA Keys

  • Parameters for RSA Public Keys
# 説明
1 n(必須) Base64urlUInt でエンコードされた RSA 公開鍵のモジュラス値
2 e(必須) Base64urlUInt でエンコードされた RSA 公開鍵の指数値(65537 = "AQAB"
  • Parameters for RSA Private Keys
# 説明
1 d(必須) Base64urlUInt でエンコードされた、RSA 秘密鍵のプライベート指数値
2 p(任意) Base64urlUInt でエンコードされた、第 1 の素因数値
3 q(任意) Base64urlUInt でエンコードされた、第 2 の素因数値
4 dp(任意) Base64urlUInt でエンコードされた、第 1 の CRT 指数値
5 dq(任意) Base64urlUInt でエンコードされた、第 2 の CRT 指数値
6 qi(任意) Base64urlUInt でエンコードされた、第 1(、第 2)の CRT 係数値
7 oth(任意) Base64urlUInt でエンコードされた、3 番目以降の素数に関する情報の配列
  • oth
    詳しくは、RFC 3447 も参照。
# 説明
1 r Base64urlUInt でエンコードされた、3 番目以降の素因数値
2 d Base64urlUInt でエンコードされた、3 番目以降の CRT 指数値
3 t Base64urlUInt でエンコードされた、3 番目以降の CRT 係数値

補足(公開してよい範囲): jwks_uri で公開するのは
公開鍵のパラメタだけである。

鍵種別 公開してよい 絶対に公開してはならない
RSA n, e d, p, q, dp, dq, qi, oth
EC x, y, crv d
oct (なし) k(共通鍵そのもの)

.NET で RSA.ExportParameters(true) の結果を
そのまま JSON 化して公開する事故が起きやすい。
引数は false(公開部分のみ)にすること。

サンプル

キー値の改行は掲載上の都合による。

JWK

RSA
  • RS256 で使用する RSA-2048
    FIDO2Web Authentication API が生成する公開鍵

    {
       "alg": "RS256",
       "e": "AQAB",
       "ext": false,
       "kty": "RSA",
       "n": "・・・"
    }
  • x5c(X.509 Certificate Chain)
    RSA 公開鍵と x5c に指定された X.509 証明書の両者で表現される
    RSA 署名鍵の JWK 表現

    {
      "kty":"RSA",
      "use":"sig",
      "kid":"1b94c",
      "n":"vrjOfz9Ccdgx5nQudyhdoR17V-IubWMeOZCwX_jj0hgAsz2J_pqYW08
      PLbK_PdiVGKPrqzmDIsLI7sA25VEnHU1uCLNwBuUiCO11_-7dYbsr4iJmG0Q
      u2j8DsVyT1azpJC_NG84Ty5KKthuCaPod7iI7w0LK9orSMhBEwwZDCxTWq4a
      YWAchc8t-emd9qOvWtVMDC2BXksRngh6X5bUYLy6AyHKvj-nUy1wgzjYQDwH
      MTplCoLtU-o-8SNnZ1tmRoGE9uJkBLdh5gFENabWnU5m1ZqZPdwS-qo-meMv
      VfJb6jJVWRpl2SUtCnYG2C32qvbWbjZ_jBPD5eunqsIo1vQ",
      "e":"AQAB",
      "x5c":
       ["MIIDQjCCAiqgAwIBAgIGATz/FuLiMA0GCSqGSIb3DQEBBQUAMGIxCzAJB
       gNVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRwwGgYD
       VQQKExNQaW5nIElkZW50aXR5IENvcnAuMRcwFQYDVQQDEw5CcmlhbiBDYW1
       wYmVsbDAeFw0xMzAyMjEyMzI5MTVaFw0xODA4MTQyMjI5MTVaMGIxCzAJBg
       NVBAYTAlVTMQswCQYDVQQIEwJDTzEPMA0GA1UEBxMGRGVudmVyMRwwGgYDV
       QQKExNQaW5nIElkZW50aXR5IENvcnAuMRcwFQYDVQQDEw5CcmlhbiBDYW1w
       YmVsbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL64zn8/QnH
       YMeZ0LncoXaEde1fiLm1jHjmQsF/449IYALM9if6amFtPDy2yvz3YlRij66
       s5gyLCyO7ANuVRJx1NbgizcAblIgjtdf/u3WG7K+IiZhtELto/A7Fck9Ws6
       SQvzRvOE8uSirYbgmj6He4iO8NCyvaK0jIQRMMGQwsU1quGmFgHIXPLfnpn
       fajr1rVTAwtgV5LEZ4Iel+W1GC8ugMhyr4/p1MtcIM42EA8BzE6ZQqC7VPq
       PvEjZ2dbZkaBhPbiZAS3YeYBRDWm1p1OZtWamT3cEvqqPpnjL1XyW+oyVVk
       aZdklLQp2Btgt9qr21m42f4wTw+Xrp6rCKNb0CAwEAATANBgkqhkiG9w0BA
       QUFAAOCAQEAh8zGlfSlcI0o3rYDPBB07aXNswb4ECNIKG0CETTUxmXl9KUL
       +9gGlqCz5iWLOgWsnrcKcY0vXPG9J1r9AqBNTqNgHq2G03X09266X5CpOe1
       zFo+Owb1zxtp3PehFdfQJ610CDLEaS9V9Rqp17hCyybEpOGVwe8fnk+fbEL
       2Bo3UPGrpsHzUoaGpDftmWssZkhpBJKVMJyf/RuP2SmmaIzmnw9JiSlYhzo
       4tpzd5rFXhjRbg4zW9C+2qok+2+qDM1iJ684gPHMIY8aLWrdgQTxkumGmTq
       gawR+N5MDtdPTEQ0XfIBc2cJEUyMTY5MPvACWpkA6SdS4xSvdXK3IVfOWA=="]
     }
  • Plaintext RSA Private Key
    認証付き暗号化オペレーションのための平文入力(プレーンテキスト)

    {
      "kty":"RSA",
      "kid":"juliet@capulet.lit",
      "use":"enc",
      "n":"t6Q8PWSi1dkJj9hTP8hNYFlvadM7DflW9mWepOJhJ66w7nyoK1gPNqFMSQRy
           O125Gp-TEkodhWr0iujjHVx7BcV0llS4w5ACGgPrcAd6ZcSR0-Iqom-QFcNP
           8Sjg086MwoqQU_LYywlAGZ21WSdS_PERyGFiNnj3QQlO8Yns5jCtLCRwLHL0
           Pb1fEv45AuRIuUfVcPySBWYnDyGxvjYGDSM-AqWS9zIQ2ZilgT-GqUmipg0X
           OC0Cc20rgLe2ymLHjpHciCKVAbY5-L32-lSeZO-Os6U15_aXrk9Gw8cPUaX1
           _I8sLGuSiVdt3C_Fn2PZ3Z8i744FPFGGcG1qs2Wz-Q",
      "e":"AQAB",
      "d":"GRtbIQmhOZtyszfgKdg4u_N-R_mZGU_9k7JQ_jn1DnfTuMdSNprTeaSTyWfS
           NkuaAwnOEbIQVy1IQbWVV25NY3ybc_IhUJtfri7bAXYEReWaCl3hdlPKXy9U
           vqPYGR0kIXTQRqns-dVJ7jahlI7LyckrpTmrM8dWBo4_PMaenNnPiQgO0xnu
           ToxutRZJfJvG4Ox4ka3GORQd9CsCZ2vsUDmsXOfUENOyMqADC6p1M3h33tsu
           rY15k9qMSpG9OX_IJAXmxzAh_tWiZOwk2K4yxH9tS3Lq1yX8C1EWmeRDkK2a
           hecG85-oLKQt5VEpWHKmjOi_gJSdSgqcN96X52esAQ",
      "p":"2rnSOV4hKSN8sS4CgcQHFbs08XboFDqKum3sc4h3GRxrTmQdl1ZK9uw-PIHf
           QP0FkxXVrx-WE-ZEbrqivH_2iCLUS7wAl6XvARt1KkIaUxPPSYB9yk31s0Q8
           UK96E3_OrADAYtAJs-M3JxCLfNgqh56HDnETTQhH3rCT5T3yJws",
      "q":"1u_RiFDP7LBYh3N4GXLT9OpSKYP0uQZyiaZwBtOCBNJgQxaj10RWjsZu0c6I
           edis4S7B_coSKB0Kj9PaPaBzg-IySRvvcQuPamQu66riMhjVtG6TlV8CLCYK
           rYl52ziqK0E_ym2QnkwsUX7eYTB7LbAHRK9GqocDE5B0f808I4s",
      "dp":"KkMTWqBUefVwZ2_Dbj1pPQqyHSHjj90L5x_MOzqYAJMcLMZtbUtwKqvVDq3
           tbEo3ZIcohbDtt6SbfmWzggabpQxNxuBpoOOf_a_HgMXK_lhqigI4y_kqS1w
           Y52IwjUn5rgRrJ-yYo1h41KR-vz2pYhEAeYrhttWtxVqLCRViD6c",
      "dq":"AvfS0-gRxvn0bwJoMSnFxYcK1WnuEjQFluMGfwGitQBWtfZ1Er7t1xDkbN9
           GQTB9yqpDoYaN06H7CFtrkxhJIBQaj6nkF5KKS3TQtQ5qCzkOkmxIe3KRbBy
           mXxkb5qwUpX5ELD5xFc6FeiafWYY63TmmEAu_lRFCOJ3xDea-ots",
      "qi":"lSQi-w9CpyUReMErP1RsBLk7wNtOvs5EQpPqmuMvqW57NBUczScEoPwmUqq
           abu9V0-Py4dQ57_bapoKRu1R90bvuFnU63SHWEFglZQvJDMeAvmj4sm-Fp0o
           Yu_neotgQ0hzbI5gry7ajdYy9-2lNx_76aBZoOUu9HCJ-UsfSOI8"
    }
Elliptic Curve DSA

P-256 Elliptic Curve の Elliptic Curve [DSS] 鍵

  • x 座標と y 座標はそれぞれ base64url エンコードされている。
  • またこの鍵自身の識別子(kid)も含まれる。
{
  "kty":"EC",
  "crv":"P-256",
  "x":"f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
  "y":"x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0",
  "kid":"Public key used in JWS spec Appendix A.3 example"
}

JWK Set

Public Keys
  • 2 つの公開鍵
    • 1 つ目は Elliptic Curve
      • 鍵が暗号化のために使用されていることを記している。
      • 鍵のマッチングの目的のために key ID を提供する。
    • 2 つ目は RSA
      • RS256 アルゴリズムで使用されていることを記している。
      • 鍵のマッチングの目的のために key ID を提供する。
{
  "keys":
    [
      {
        "kty":"EC",
        "crv":"P-256",
        "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
        "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
        "use":"enc",
        "kid":"1"
      },
      {
        "kty":"RSA",
        "n":"0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx
            4cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMs
            tn64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2
            QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbI
            SD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqb
            w0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
        "e":"AQAB",
        "alg":"RS256",
        "kid":"2011-04-29"
      }
    ]
}
Private Keys
  • 公開鍵と秘密鍵の値
    • 1 つ目は Elliptic Curve
    • 2 つ目は RSA
{
  "keys":
    [
      {
        "kty":"EC",
        "crv":"P-256",
        "x":"MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
        "y":"4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
        "d":"870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE",
        "use":"enc",
        "kid":"1"
      },
      {
        "kty":"RSA",
        "n":"0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4
            cbbfAAtVT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMst
            n64tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FDW2Q
            vzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n91CbOpbIS
            D08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINHaQ-G_xBniIqbw
            0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw",
        "e":"AQAB",
        "d":"X4cTteJY_gn4FYPsXB8rdXix5vwsg1FLN5E3EaG6RJoVH-HLLKD9
            M7dx5oo7GURknchnrRweUkC7hT5fJLM0WbFAKNLWY2vv7B6NqXSzUvxT0_YSfqij
            wp3RTzlBaCxWp4doFk5N2o8Gy_nHNKroADIkJ46pRUohsXywbReAdYaMwFs9tv8d
            _cPVY3i07a3t8MN6TNwm0dSawm9v47UiCl3Sk5ZiG7xojPLu4sbg1U2jx4IBTNBz
            nbJSzFHK66jT8bgkuqsk0GjskDJk19Z4qwjwbsnn4j2WBii3RL-Us2lGVkY8fkFz
            me1z0HbIkfz0Y6mqnOYtqc0X4jfcKoAC8Q",
        "p":"83i-7IvMGXoMXCskv73TKr8637FiO7Z27zv8oj6pbWUQyLPQBQxtPV
            nwD20R-60eTDmD2ujnMt5PoqMrm8RfmNhVWDtjjMmCMjOpSXicFHj7XOuVIYQyqV
            WlWEh6dN36GVZYk93N8Bc9vY41xy8B9RzzOGVQzXvNEvn7O0nVbfs",
        "q":"3dfOR9cuYq-0S-mkFLzgItgMEfFzB2q3hWehMuG0oCuqnb3vobLyum
            qjVZQO1dIrdwgTnCdpYzBcOfW5r370AFXjiWft_NGEiovonizhKpo9VVS78TzFgx
            kIdrecRezsZ-1kYd_s1qDbxtkDEgfAITAG9LUnADun4vIcb6yelxk",
        "dp":"G4sPXkc6Ya9y8oJW9_ILj4xuppu0lzi_H7VTkS8xj5SdX3coE0oim
            YwxIi2emTAue0UOa5dpgFGyBJ4c8tQ2VF402XRugKDTP8akYhFo5tAA77Qe_Nmtu
            YZc3C3m3I24G2GvR5sSDxUyAN2zq8Lfn9EUms6rY3Ob8YeiKkTiBj0",
        "dq":"s9lAH9fggBsoFR8Oac2R_E2gw282rT2kGOAhvIllETE1efrA6huUU
            vMfBcMpn8lqeW6vzznYY5SSQF7pMdC_agI3nG8Ibp1BUb0JUiraRNqUfLhcQb_d9
            GF4Dh7e74WbRsobRonujTYN1xCaP6TO61jvWrX-L18txXw494Q_cgk",
        "qi":"GyM_p6JrXySiz1toFgKbWV-JdI3jQ4ypu9rbMWx3rQJBfmt0FoYzg
            UIZEVFEcOqwemRN81zoDAaa-Bk0KWNGDjJHZDdDmFhW3AN7lI-puxk_mHZGJ11rx
            yR8O55XLSe3SPmRfKwZI6yU24ZxvQKFYItdldUKGzO6Ia6zTKhAVRU",
        "alg":"RS256",
        "kid":"2011-04-29"
      }
    ]
  }
Symmetric Keys
  • 2 つの対称鍵
    • 1 つ目は AES Key Wrap
    • 2 つ目は HMAC key
{
  "keys":
    [
      {
        "kty":"oct",
        "alg":"A128KW",
        "k":"GawgguFyGrWKav7AX4VKUg"
      },
      {
        "kty":"oct",
        "k":"AyM1SysPpbyDfgZld3umj1qzKObwVMkoqQ-EstJQLr_T-1qS0gZH75
            aKtMN3Yj0iPS4hcgUuTwjAzZr1Z9CAow",
        "kid":"HMAC key used in JWS spec Appendix A.1 example"}
    ]
}

移行メモ: 元ページの「2 つの対象鍵」は
「2 つの対称鍵」(symmetric)の変換ミスと思われるため正した。

自作ライブラリ

署名・暗号化アルゴリズム

.NETの署名・暗号化アルゴリズムの署名・暗号化アルゴリズムを
使用すると良い。

RSAParameters

X.509 証明書 ---> RSAParameters <---> JWK 変換を考える。

.NET

.NET では以下のようにできる模様。

補足(最新化): RSAParameters を経由した手書きの変換は、
現在はほぼ不要になっている。

  • .NET: Microsoft.IdentityModel.Tokens
    JsonWebKey / JsonWebKeyConverter
    X509SecurityKeyJsonWebKey の相互変換を提供する。
  • 手作業で行う場合の注意点は
    Base64urlUInt は先頭 0 パディングを含まない符号なし整数」であること。
    .NET の RSAParameters.Modulus は固定長バイト配列なので、
    先頭のゼロ バイトの扱いで不一致が起きやすい。

他の言語

同じようなことは他の言語でも調査されている。

参考

mkjwk

Qiita

移行メモ(最新化): 元ページのリンクは .../oauth2/v2/certs だったが、
現在 Google が JWK Set を公開しているのは
https://www.googleapis.com/oauth2/v3/certs である(v2 は X.509 形式)。
実装上は、URL を直書きせず
https://accounts.google.com/.well-known/openid-configuration
jwks_uri から解決するのが正しい。

  • JWA - JWK用(JWA

Tags: 移行, IT国際標準, プログラミング, 通信技術, 認証基盤, クレームベース認証, 暗号化

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally