「[[マイクロソフト系技術情報 Wiki>http://techinfoofmicrosofttech.osscons.jp/]]」は、「[[Open棟梁Project>https://github.com/OpenTouryoProject/]]」,「[[OSSコンソーシアム .NET開発基盤部会>https://www.osscons.jp/dotNetDevelopmentInfrastructure/]]」によって運営されています。

-[[戻る>JWT]]

* 目次 [#pd2a93b9]
#contents

*概要 [#c95ff4a8]
以下の内容で最終確認済み。~
https://tools.ietf.org/html/rfc7515

-ざっくり言って「[[MACや署名>#f7edb04c]]付きの JWT = JWS」
-JWT と言えば、だいたい、JWSの事を言う。

-JWSは、暗号化ではなく[[署名>#f7edb04c]]なので、JSON の中身は誰でも見られる。
-通常、発行者だけが秘密鍵で検証できるが、
--秘密鍵を使用すれば発行者だけが検証可能。
--公開鍵を使用すれば誰でも検証可能。

-[[OpenID Connect]]のID Tokenなどで利用されている。~
[[OAuth]]2のAccess Tokenとしても使用されている。

*構成要素 [#v48fc731]

**[[JOSEヘッダ>JWT#m9c6f99a]] [#u5c396b1]
JWSの基本的なヘッダ(≒[[JWS Compact Serialization>#xe1c18e7]]の場合の[[保護ヘッダ>#ab3d5ae0]])には、以下のものがある。

***ヘッダの例 [#b52fd6be]
-[[HS256>#b8d0ee68]]~
秘密鍵で検証可能なHS256(HMAC using SHA-256 hash)
 {
   "alg": "HS256",
   "typ": "JWT"
 }

-[[RS256>#xe033b54]]~
公開鍵で検証可能なRS256(RSA using SHA-256 hash)
 {
   "alg": "RS256",
   "typ": "JWT"
 }

-[[ES256>#b8d0ee68]]~
公開鍵で検証可能なES256(ECDSA using P-256 and SHA-256)
 {
   "alg": "ES256",
   "typ": "JWT"
 }

***追加のパラメタ [#tc7fd975]
-[[JWK]]をサポートする場合~
jwk, kid & jkuなどのパラメタを追加する。

-[[証明書]]をサポートする場合
--x5u(X.509 URL)ヘッダ・パラメタ~
PEMエンコーディング
--x5c(X.509証明書チェーン)ヘッダ・パラメタ~
DERエンコーディングのbase64url
--x5t(X.509証明書SHA-1拇印)ヘッダ・パラメタ~
DERエンコーディングのbase64url
--x5t#S256(X.509証明書SHA-256拇印)~
DERエンコーディングのbase64url

-その他のパラメタ
--[[typ>JWT#m9c6f99a]]
--[[cty>JWT#m9c6f99a]]

***TLS要件 [#x222cc1c]
"jku" and / or "x5u"ヘッダパラメタをサポートする実装は、TLSが必要。

**[[ペイロード(クレームセット)>JWT#m5b94cda]] [#h15b0503]

**署名 [#f7edb04c]
-色々な暗号化アルゴリズムを使用して作成した署名
-署名の検証キーの共有方法には以下の方法が有る。
--検証用エンドポイントを使用する。
--[[JWK]]を使用する。
--[[X.509証明書>証明書]]を使用する。

-参考 : OpenID Connect の署名検証 - Carpe Diem~
http://christina04.hatenablog.com/entry/2015/01/27/131259
--検証方法①:Googleの検証用エンドポイントを利用する
--検証方法②:IdP(Google)の提供している公開鍵を使って自分で検証する
---公開鍵①:[[JWK]](JSON Web Key)を使う
---公開鍵①:[[X.509証明書>証明書]]を使う

*詳細 [#u6d67bd4]

**表現(エンコード) [#xd09f92e]
-[[構成要素>#v48fc731]]([[ヘッダ>#u5c396b1]]、[[ペイロード(クレームセット)>#h15b0503]]、[[署名>#f7edb04c]])を以下のように表現(エンコード)したもの。
-以下の2つの表現(エンコード)方法があり、どちらでも、[[構成要素>#v48fc731]]は、base64urlでエンコードされる。

***JWS Compact Serialization [#xe1c18e7]
多くの場合は、この表現(エンコード)。

-[[署名>#f7edb04c]]付きのデータを JSON (の Base64 URL Encode) 形式で表現する。
-「Base64」ではなく「Base64 &color(red){URL};」なので「=」は含まれない。

-例~
[[ヘッダ>#u5c396b1]].[[ペイロード(クレームセット)>#h15b0503]].[[署名>#f7edb04c]]
 BASE64URL (UTF-8 (Header))
 .
 BASE64URL (UTF-8 (Claim Set))
 .
 BASE64URL (UTF-8 (Signature))

※ 殆どの場合、こちらが使用されている。

***JWS JSON Serialization [#t41a19b3]
-あまり市民権を獲得しているようには思えない表現(エンコード)。
--pure な JSON として表現されるフォーマット
--URL-Safe でもなければコンパクトでもない。
--[[MACや署名>#f7edb04c]]を複数持てるといった違いがある。

-Syntax
--"protected" = BASE64URL(UTF8([[保護ヘッダ>#ab3d5ae0]]))
--"signatures"
---"header" = [[非保護ヘッダ>#c189dceb]](JSON)
---"payload" = BASE64URL([[ペイロード(クレームセット)>#h15b0503]])
---"signature" = BASE64URL([[署名>#f7edb04c]])
     {
      "payload":"<payload contents>",
      "signatures":[
       {"protected":"<integrity-protected header 1 contents>",
        "header":<non-integrity-protected header 1 contents>,
        "signature":"<signature 1 contents>"},
       ...
       {"protected":"<integrity-protected header N contents>",
        "header":<non-integrity-protected header N contents>,
        "signature":"<signature N contents>"}]
     }

-Example
--Complete JWS JSON Serialization Representation
     {
      "payload":
       "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGF
        tcGxlLmNvbS9pc19yb290Ijp0cnVlfQ",
      "signatures":[
       {"protected":"eyJhbGciOiJSUzI1NiJ9",
        "header":
         {"kid":"2010-12-29"},
        "signature":
         "cC4hiUPoj9Eetdgtv3hF80EGrhuB__dzERat0XF9g2VtQgr9PJbu3XOiZj5RZ
          mh7AAuHIm4Bh-0Qc_lF5YKt_O8W2Fp5jujGbds9uJdbF9CUAr7t1dnZcAcQjb
          KBYNX4BAynRFdiuB--f_nZLgrnbyTyWzO75vRK5h6xBArLIARNPvkSjtQBMHl
          b1L07Qe7K0GarZRmB_eSN9383LcOLn6_dO--xi12jzDwusC-eOkHWEsqtFZES
          c6BfI7noOPqvhJ1phCnvWh6IeYI2w9QOYEUipUTI8np6LbgGY9Fs98rqVt5AX
          LIhWkWywlVmtVrBp0igcN_IoypGlUPQGe77Rw"},
       {"protected":"eyJhbGciOiJFUzI1NiJ9",
        "header":
         {"kid":"e9bc097a-ce51-4036-9562-d2ade882db0d"},
        "signature":
         "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8IS
          lSApmWQxfKTUJqPP3-Kg6NU1Q"}]
     }
--JWS Using Flattened JWS JSON Serialization~
[[MACや署名>#f7edb04c]]が 1 つのみの場合は Flattened JWS JSON Serialization を使える。
     {
      "payload":
       "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGF
        tcGxlLmNvbS9pc19yb290Ijp0cnVlfQ",
      "protected":"eyJhbGciOiJFUzI1NiJ9",
      "header":
       {"kid":"e9bc097a-ce51-4036-9562-d2ade882db0d"},
      "signature":
       "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8IS
        lSApmWQxfKTUJqPP3-Kg6NU1Q"
     }

**保護ヘッダ・非保護ヘッダ [#h28e2498]
[[JOSEヘッダ>#u5c396b1]]は、以下のメンバの和集合。

-[[JWS Compact Serialization>#xe1c18e7]]の場合は、[[JOSEヘッダ>#u5c396b1]] ≒ [[保護ヘッダ>#ab3d5ae0]]。
-[[JWS JSON Serialization>#t41a19b3]]の場合は、[[JOSEヘッダ>#u5c396b1]] ≒ [[保護ヘッダ>#ab3d5ae0]] and / or [[非保護ヘッダ>#c189dceb]]

***保護ヘッダ [#ab3d5ae0]
[[MACや署名>#f7edb04c]]によって完全性が保護されているヘッダ・パラメタを含むJSONオブジェクト。
-[[JWS Compact Serialization>#xe1c18e7]]の場合、これは[[JOSEヘッダ>#u5c396b1]]全体で構成される。
-[[JWS JSON Serialization>#t41a19b3]]の場合、
--これは[[JOSEヘッダ>#u5c396b1]]の1コンポーネント。
--用例を解析してみると、[[JOSEヘッダ>#u5c396b1]]中の"alg"パラメタが抽出されている。

***非保護ヘッダ [#c189dceb]
-これは、[[JWS JSON Serialization>#t41a19b3]]を使用する場合にのみ存在。
--[[JOSEヘッダ>#u5c396b1]]の1コンポーネントであるが、
--こちらは、[[署名>#f7edb04c]]の作成には利用されない。

-完全性保護されていないヘッダ・パラメタを含むJSONオブジェクト。
-用例を解析してみると、[[JOSEヘッダ>#u5c396b1]]中の"kid"パラメタが抽出されている。~
(...kidが改ざんされると検証できなくなるだけなので、保護しなくてもイイためとは言えそう)

**アルゴリズム [#f133bbd2]
認証系であれば公開鍵暗号化方式のRS256(RSA using SHA-256 hash)が良い。

***[[HS256>#a022059c]] [#b8d0ee68]
キー付きハッシュである、alg=HS256(HMAC-SHA256)によるMAC付与

***[[RS256>#f0f0bbd5]] [#xe033b54]
公開鍵暗号方式である、alg=RS256(RSA-SHA256)による署名を行う。

***[[ES256>#f864ece6]] [#b8d0ee68]
公開鍵暗号方式である、alg=ES256(ECDSA using P-256 and SHA-256)による署名を行う。

-WebCrypto APIでECDSAの署名と検証を試してみる~
https://qiita.com/tomoyukilabs/items/b346a71a920eb7a93501

***[[JWAを確認>JWA#zcf6ef0e]] [#ldcf5f58]

*手順 [#e7dc0563]

**作成 [#paf2520a]

***[[JWS Compact Serialization>#xe1c18e7]]の場合 [#v2b3afc3]
-JWSを[[JOSEヘッダ>#u5c396b1]]( = [[保護ヘッダ>#ab3d5ae0]])、[[ペイロード(クレームセット)>#h15b0503]]のJSONを生成し、
--[[JOSEヘッダ>#u5c396b1]]( = [[保護ヘッダ>#ab3d5ae0]])をUTF-8のバイト文字列に変換し、BASE64urlでエンコード。
--[[ペイロード(クレームセット)>#h15b0503]]をUTF-8のバイト文字列に変換し、BASE64urlでエンコード。

-BASE64urlエンコード済みの[[ヘッダ>#u5c396b1]]と[[ペイロード(クレームセット)>#h15b0503]]をピリオドで連結、
-上記をヘッダで指定した暗号化プロバイダで[[MAC・署名>#f7edb04c]]を生成し、BASE64urlエンコードし、当該要素をピリオドで連結する。

***[[JWS JSON Serialization>#t41a19b3]]の場合 [#n5013210]
[[JWS Compact Serialization>#v2b3afc3]]との差異は以下。
-[[JOSEヘッダ>#u5c396b1]]( = [[保護ヘッダ>#ab3d5ae0]] and / or [[非保護ヘッダ>#c189dceb]])
-[[非保護ヘッダ>#c189dceb]]は、[[MAC・署名>#f7edb04c]]の生成に使用されない。
-必要に応じて、[[MAC・署名>#f7edb04c]]の生成を繰り返す。

**検証 [#ib69bb72]

***[[JWS Compact Serialization>#xe1c18e7]]の場合 [#h0733282]
-JWSを[[JOSEヘッダ>#u5c396b1]]( = [[保護ヘッダ>#ab3d5ae0]])、[[ペイロード(クレームセット)>#h15b0503]]、[[MAC・署名>#f7edb04c]]に分割し
--[[JOSEヘッダ>#u5c396b1]]( = [[保護ヘッダ>#ab3d5ae0]])をBASE64urlでデコードし、UTF-8に変換。
--[[ペイロード(クレームセット)>#h15b0503]]をBASE64urlをBASE64urlでデコードし、UTF-8に変換。
--[[MAC・署名>#f7edb04c]]をBASE64urlでデコード。

-[[JOSEヘッダ>#u5c396b1]]のJSONから[[JWT]]の種類(JWS)、暗号化プロバイダを確認する。
-[[署名方法>#f7edb04c]](暗号化プロバイダ、キー)を考慮してJWSの検証を行なう。
-検証完了後、[[ペイロード(クレームセット)>#h15b0503]]のJSON内の有効期限の検証も行なう。

***[[JWS JSON Serialization>#t41a19b3]]の場合 [#r2711dff]
[[JWS Compact Serialization>#h0733282]]との差異は以下。
-[[JOSEヘッダ>#u5c396b1]]( = [[保護ヘッダ>#ab3d5ae0]] and / or [[非保護ヘッダ>#c189dceb]])
-[[非保護ヘッダ>#c189dceb]]は、[[MAC・署名>#f7edb04c]]の検証に使用されない。
-必要に応じて、[[MAC・署名>#f7edb04c]]の検証を繰り返す。

***検証サイト [#s7ab5c53]
[[下記参照>#ma412b10]]

**具体例 [#kf4aed55]

***HS256 [#f0f0bbd5]
https://tools.ietf.org/html/rfc7515#appendix-A.1

***RS256 [#a022059c]
https://tools.ietf.org/html/rfc7515#appendix-A.2

***ES256 [#f864ece6]
https://tools.ietf.org/html/rfc7515#appendix-A.3

*セキュリティに関する考慮事項 [#w471ec3d]

**鍵エントロピー [#fbee1394]
すべての鍵に最低128ビットのエントロピーを使用する必要がある。~
コンテキスト次第で、さらに多くのエントロピーが必要になる可能性がある。

**ランダム値 [#r57b31fe]
-パブリック/プライベートキーペア、MACキー、パディング値をランダムに生成する必要がある。
-暗号鍵を生成するために適切な擬似乱数生成器(PRNG)を使用する。~
(.NETでは、PRNGとして、[[RNGCryptoServiceProvider>.NETの署名・暗号化アルゴリズム#feec3024]]を使用する。)

**鍵の識別 [#r1983004]
仕様の外だが、以下を使用できる。

***[[JOSEヘッダ中のJWK>#tc7fd975]] [#b25869e4]

***[[JOSEヘッダ中の証明書>#tc7fd975]] [#af6eab4b]

**鍵の保護、発信元認証 [#r0e185a0]

***MAC [#l1bb5bc3]
-保護
--MACキーを保護する必要がある。
--MACキーが破損すると、認証されたコンテンツの変更が検出されなくなる可能性がある。

-発信元認証~
鍵の出所の認証が必要。

***署名 [#u9fca186]
-保護
--秘密鍵を保護する必要がある。
--署名者の秘密鍵が侵害されると、攻撃者は署名者になりすますことができる。

-発信元認証~
データ発信元の認証が必要。

**署名とMACの違い [#gad89ae5]

-共通点
--完全性チェックを提供~
完全性値が計算されてからメッセージが変更されていないことを確認

-相違点~
セキュリティプロパティにはいくつかの重要な違いがある。

***[[MAC>暗号化アルゴリズム#w5550a92]] [#w0fb8273]
-特定の状況下でのみ発信識別を提供するため、~
第三者への発信を証明するために使用できない。

--MACキーが2つのエンティティにしか知られておらず、受信者がメッセージを作成していないことが分かっている場合にのみ発信を判断できる。
--これは、メッセージが対称MACキーを知っている当事者のうちの1つによって生成されたという裏付けを提供するだけ。 

-秘密鍵とMACキー
--秘密鍵~
単一のエンティティの手元にある
--MACキー~
整合性の計算と検査にMACキーを使用するすべてのエンティティの手元にある必要がある。~

※ HS256はプレーンなHMACでMACではない(ややこしい)。

***[[署名>暗号化アルゴリズム#leddd7f0]] [#kc1e2e24]

**暗号の敏捷性 [#m612b6da]
[[JWA]]を参照

*自作ライブラリ [#a945c75c]

**署名・暗号化アルゴリズム [#p4042a8b]
[[ココ>.NETの署名・暗号化アルゴリズム]]の署名・暗号化アルゴリズムを使用すると良い。

***KeyedHashAlgorithm [#a86f6259]
-HS256(HMAC using SHA-256 hash)
--HMACSHA256 クラス (System.Security.Cryptography)~
https://msdn.microsoft.com/ja-jp/library/system.security.cryptography.hmacsha256.aspx

***AsymmetricAlgorithm [#oc7f2c3b]
-RS256(RSA using SHA-256 hash)
--RSACryptoServiceProvider クラス (System.Security.Cryptography)~
https://msdn.microsoft.com/ja-jp/library/system.security.cryptography.rsacryptoserviceprovider.aspx
--Using RSACryptoServiceProvider for RSA-SHA256 signatures – .NET Security Blog~
https://blogs.msdn.microsoft.com/shawnfa/2008/08/25/using-rsacryptoserviceprovider-for-rsa-sha256-signatures/

-ES256(ECDSA using P-256 and SHA-256)
--ECDsa クラス (System.Security.Cryptography)~
https://msdn.microsoft.com/ja-jp/library/system.security.cryptography.ecdsa.aspx

-PS256(RSASSA-PSS using SHA-256 and MGF1 with SHA-256)

**参考サイト [#e11d0494]
以下が参考になる。

-IdM実験室: [JWT/OAuth]Service Accountを使ってGoogle APIを利用する②~
http://idmlab.eidentity.jp/2015/01/jwtoauthservice-accountgoogle-api_5.html

ココを見ると、
-{ alg = "RS256", typ = "JWT" }と言うヘッダで、
-RSACryptoServiceProvider + X509Certificate2の署名を行っており、

これで、実際にGoogle側での検証ができている。

**検証サイト [#ma412b10]
上記のように、RFCを正確に理解していないとJWTライブラリ作成は難しいが、~
[[JSON Web Tokens - jwt.io>https://jwt.io/]]などの検証サイトを使用して検証できれば、及第点に達していると言える。

以下のように検証できる。

***手順 [#yf87387f]
+左ペイン(Encoded)にJWTの文字列を貼り付ける。
+すると、入力したJWTから、ペイン(Dencoded)のHeader、Payloadに自動的に表示がなされる。
+次に、上部 ALGORITHM selectbox から、Headerに表示された"alg"と同じアルゴリズムを選択する。
+最後に、VERIFY SIGNATUREに、署名の検証に使用するキーを入力する([[HS256の場合>#b6059f50]]と[[RS256の場合>#hbd54613]]で異なる)。

***HS256の場合 [#b6059f50]
HS256は非常に単純で、署名に使用したキーのBase64(Base64Url)表現を指定する。

#ref(HS256.png,left,nowrap,HS256,50%)

***RS256の場合 [#hbd54613]
RS256は署名に使用した秘密鍵に対応する公開鍵を指定する。~
私は、[[X.509証明書>証明書]]を利用したので、[[OpenSSLで公開鍵を取得して>証明書#tb47e80e]]、それを貼り付けた所、検証ができた。~

ポイントは、
-「-----BEGIN PUBLIC KEY-----」
-     「公開鍵」
-「-----END PUBLIC KEY-----」

と、ヘッダ・フッタ部分も貼り付ける必要がある所だろうか。

#ref(RS256.png,left,nowrap,RS256,50%)

***Open棟梁 [#c4289f7f]
-JWTの生成と検証 - Open 棟梁 Wiki~
https://opentouryo.osscons.jp/index.php?JWT%E3%81%AE%E7%94%9F%E6%88%90%E3%81%A8%E6%A4%9C%E8%A8%BC

*参考 [#y2ab180f]
-RFC 7515 - JSON Web Signature (JWS)~
https://tools.ietf.org/html/rfc7515

-JSON Web Signature (JWS) 日本語訳~
https://openid-foundation-japan.github.io/draft-ietf-jose-json-web-signature-14.ja.html

-複雑に関係しあうJWTまわりの仕様を見る: JWS (JSON Web Signature) - 理系学生日記~
http://kiririmode.hatenablog.jp/entry/20170225/1488020088

**[[JWA - JWS用>JWA#zcf6ef0e]] [#xd6c0477]

**[[暗号化アルゴリズム]] [#gc5974cd]
***[[.NETの署名・暗号化アルゴリズム]] [#db2f0e77]

----
Tags: [[:IT国際標準]], [[:認証基盤]], [[:クレームベース認証]], [[:暗号化]]

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS