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

-[[戻る>JWT]]

* 目次 [#pd2a93b9]
#contents

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

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

-OpenID Connect の ID Tokenなどで利用されている。

*構成要素 [#v48fc731]

**[[ヘッダ>JWT#m9c6f99a]] [#u5c396b1]
JWSの基本的なヘッダには、

-秘密鍵で検証可能なHS256(HMAC using SHA-256 hash)
 {
   "alg": "HS256",
   "typ": "JWT"
 }

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

などがある。

**[[ペイロード(クレームセット)>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]
[[ヘッダ>#u5c396b1]]、[[ペイロード(クレームセット)>#h15b0503]]、[[署名>#f7edb04c]]を以下のように[[表現(エンコード)>#xd09f92e]]したもの。

**表現(エンコード) [#xd09f92e]
以下の2つの表現(エンコード)方法がある。

***JWS Compact Serialization [#xe1c18e7]

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

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

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

***RS256 [#xe033b54]
alg=RS256(RSA-SHA256)による署名を行う。

-フォーマット([[JWS Compact Serialization>#xe1c18e7]])
--[[ヘッダ>#u5c396b1]].[[ペイロード(クレームセット)>#h15b0503]].[[署名>#f7edb04c]]
--
 BASE64URL (UTF-8 (Header))
 .
 BASE64URL (UTF-8 (Claim Set))
 .
 BASE64URL (UTF-8 (Signature))

***HS256 [#b8d0ee68]
alg=HS256(HMAC-SHA256)によるMAC付与

-フォーマット([[JWS Compact Serialization>#xe1c18e7]])

*手順 [#e7dc0563]
**作成 [#paf2520a]
-[[ヘッダ>#u5c396b1]]を生成し、UTF-8のバイト文字列に変換し、BASE64urlエンコード。
-[[ペイロード(クレームセット)>#h15b0503]]を生成し、UTF-8のバイト文字列に変換し、BASE64urlエンコード。
-BASE64urlエンコード済みの[[ヘッダ>#u5c396b1]]と[[ペイロード(クレームセット)>#h15b0503]]を~
ピリオドで連結する、UTF-8バイト文字列に変換し、BASE64urlエンコード。
-上記をヘッダで指定した暗号化プロバイダで署名し、[[署名>#f7edb04c]]の要素を追加する。

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

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

*自作ライブラリ [#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/

**参考サイト [#e11d0494]
ちなみに、

-C#と.NETを使ってJsonWebTokenをRS256で署名して作成する方法 - ぺぷしのーげん~
http://www.pepsinogen.blog/entry/2016/06/19/C%23%E3%81%A8_NET%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6JsonWebToken%E3%82%92RS256%E3%81%A7%E7%BD%B2%E5%90%8D%E3%81%97%E3%81%A6%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95

は、

-ToXmlString、FromXmlStringのXML文字列を使用できるか?
-この署名の方法と、ヘッダの表記はあっているか?

が記載されていない。

また、

-oauth - Is there a JSON Web Token (JWT) example in C#? - Stack Overflow~
http://stackoverflow.com/questions/10055158/is-there-a-json-web-token-jwt-example-in-c

は、いくつか誤りがあるようで、RS256は、HMACSHA256ではない。

故に、(実際にGoogle側での検証ができているので)こちらのほうが参考になる。

-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側での検証ができている。

秘密鍵・公開鍵のキーペアを、

-ToXmlStringmethod()メソッドによって生成するか?
--一応、[[RFC 3275 - XML-Signature Syntax and Processing - 4.4 The KeyInfo Element>https://www.ietf.org/rfc/rfc3275.txt]]で標準規格化されているもよう。
--そもそも、「KeyInfo Element(DSAKeyValue, RSAKeyValue Elementなど)」サポートされているか?
-X509Certificate2 クラスを使用してX.509 証明書から取得するか?

検討(検証)する必要が出てくる。

**検証サイト [#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

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

----
Tags: [[:認証基盤]], [[:クレームベース認証]], [[:暗号化]]

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