今日はJSON Simple Sign 1.0 draft 01を読む時間を作ったのであとで忘れないようにメモを残す。
これを使えば、OAuth 2.0のレスポンスに使われているJSON形式のレスポンスに署名をつけたりできます。
仕様メモ
Abstract
この仕様はJSONにシンプルな署名をするメカニズムを定義しています。
2. Signature Parameters
署名を作成するためのアルゴリズムや証明書の場所などのパラメータ。
- algorithm
- thumprint
- certs_uri
- key_id
2.1 JSON Serialization
JSONオブジェクトの配列にしたもの。
2.2 Web Token Serialization
JSON Serializationをbase64url eoncodeしたものがWeb Token Serializationである。
こいつを"ascii armoured sig_params"と呼ぶ。
3. Creating Signature
署名作成方法は以下の手順。
1. 署名対象のデータをBase64 URLエンコードして"ascii armoured payload"を作成する
2. "ascii armoured payload"と指定された署名アルゴリズムから"signature"を作成する
3. "signature"をBase64 URLエンコードして"signature string"を作成する
4. Serialization
ここでも2種類のSerializationを定義されている。
4.1. JSON Serialization
JSON Serializationでは、"signature string" と "ascii armoured payload"をJSONエンベローブにつっこむ。
{ "type": "http://openid.net/specs/ab/1.0#jss", ★Serializationの種類(オプション) "data_type": "application/json", ★データの種類 "data": "eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsIjAiOiJwYXlsb2FkIn0", ★署名対象のデータをBase64 URLエンコードしたもの。いわゆる"ascii armoured payload" "sig_params": [ { "key_id": "example.com", "algorithm": "HMAC-SHA256" } ], ★2.1で定義されてる署名パラメータ "sigs": [ "cfXgu64BQGFSQrY0ZcJBZASMvYvTHu9GQ0YM9rjPSso" ] ★"signature string" } { "type": "http://openid.net/specs/ab/1.0#jss", "data_type": "application/json", "data": "ewogICAgImF1ZGllbmNlIjogImh0dHBzOi8vZXhhbXBsZS1jbGllbnQuY29tL3Jl ZGlyZWN0X3VyaSIsCiAgICAib2F1dGhfdG9rZW4iOiAiYXNkZmprbHNkZmp3b0lq ZmsiLAogICAgIm5vdF9hZnRlciI6IDEyMzQ1Njc4LAogICAgInVzZXJfaWQiOiAi MTIyMyIsCiAgICAicHJvZmlsZV9pZCI6ICIxMjIzIgp9", "sig_params": [ { "certs_uri": "https://example.com/mycerts.pem" }, ★1個めの署名パラメータ { "algorithm": "RSA-SHA1", "certs_uri": "https://example.org/mycerts.pem" } ★2個めの署名パラメータ ] , "sigs": [ "wm21w_Ppdil0f1HrSyiftu5pWrESclxxC2ON4-Vd1bJj3wlkFb3aoIWrT8TjMiey QKkHNgYwezeyvB_EuXnlOR2LZICXrsfAh65gHHynKI_NEgHHVFTt6msqP-wUru6f hV1cNAzRgZ6iFoNz6fRkWld1Guh5W6mncBfzWooq4OiAWt1JoHQz_pBc1a2cuGIM m5T9T_D8IxKYxnU6H7S56Be0hoaUV37PTbXSAG08_lkl84oSJtJ1Zvxh4c9ycXCd cg-VZ5isJsRnKjAqYeexPKg9683CG3iAB3Y7ZdZelstehpOEvkg9bn8BjkhjoOLk efeN_vZsXJGPvYJIeFav3A", ★1個めの署名 "phLdlfjLEcA5-WOIoIu_CK_eIQV6Mswf9QfDTcpiehiptvDAAIkXo6oyJXVGIB7E RxaZ95-3okshSSj0mG4tFunTmV55nBV8zPoHQoxtWrWiksiVMYyG_yRG11xuCXkp XVper_fsJ1VJkP8FStYA3DY5E4e4FoV_wZsRvMMot88IPIFcFBmlBBGrdfEVkQBD -1sS0PWCLGFOQXrOWZysS9TfiRicPHtmW5gH9hOhGA97n4RwaIMXCjLVjpqvDhT7 8akYpSQSN53PyaSlo99ffgDpc8Asy0FKNVSQpCqYg6G6BFTj12tt0JTIcH5U8RnI fN8bVrcu578pDx1-bwfVkg" ★2個めの署名 ] }
4.2. Web Token Serialization
"signature string", "ascii armoured sig_params", "ascii armoured payload"をピリオドで連結する。
"ascii armoured sig_params"が固定(最初から決まってるときとか)は省略できる。
98024bab1652fcc65b4948e71473d19a572ff969e11be10eb1b1deee415dea27(★"signature string") . W3sia2V5X2lkIjogImV4YW1wbGUuY29tIiwiYWxnb3JpdGhtIjogIkhNQUMtU0hBMjU2In1d(★"ascii armoured sig_params") . ewogICAgImF1ZGllbmNlIjogImh0dHBzOi8vZXhhbXBsZS1jbGllbnQuY29tL3Jl ZGlyZWN0X3VyaSIsCiAgICAib2F1dGhfdG9rZW4iOiAiYXNkZmprbHNkZmp3b0lq ZmsiLAogICAgIm5vdF9hZnRlciI6IDEyMzQ1Njc4LAogICAgInVzZXJfaWQiOiAi MTIyMyIsCiAgICAicHJvZmlsZV9pZCI6ICIxMjIzIgp9(★"ascii armoured payload") # "ascii armoured sig_params"を省略した場合 98024bab1652fcc65b4948e71473d19a572ff969e11be10eb1b1deee415dea27(★"signature string") . ewogICAgImF1ZGllbmNlIjogImh0dHBzOi8vZXhhbXBsZS1jbGllbnQuY29tL3Jl ZGlyZWN0X3VyaSIsCiAgICAib2F1dGhfdG9rZW4iOiAiYXNkZmprbHNkZmp3b0lq ZmsiLAogICAgIm5vdF9hZnRlciI6IDEyMzQ1Njc4LAogICAgInVzZXJfaWQiOiAi MTIyMyIsCiAgICAicHJvZmlsZV9pZCI6ICIxMjIzIgp9(★"ascii armoured payload")
署名が複数ある場合は、2個の"signature string"を連結させる。このときは"ascii armoured sig_params"を省略できないので連結する文字列の数は4個以上になる。
wm21w_Ppdil0f1HrSyiftu5pWrESclxxC2ON4-Vd1bJj3wlkFb3aoIWrT8TjMiey QKkHNgYwezeyvB_EuXnlOR2LZICXrsfAh65gHHynKI_NEgHHVFTt6msqP-wUru6f hV1cNAzRgZ6iFoNz6fRkWld1Guh5W6mncBfzWooq4OiAWt1JoHQz_pBc1a2cuGIM m5T9T_D8IxKYxnU6H7S56Be0hoaUV37PTbXSAG08_lkl84oSJtJ1Zvxh4c9ycXCd cg-VZ5isJsRnKjAqYeexPKg9683CG3iAB3Y7ZdZelstehpOEvkg9bn8BjkhjoOLk efeN_vZsXJGPvYJIeFav3A(★1個目の"signature string") . phLdlfjLEcA5-WOIoIu_CK_eIQV6Mswf9QfDTcpiehiptvDAAIkXo6oyJXVGIB7E RxaZ95-3okshSSj0mG4tFunTmV55nBV8zPoHQoxtWrWiksiVMYyG_yRG11xuCXkp XVper_fsJ1VJkP8FStYA3DY5E4e4FoV_wZsRvMMot88IPIFcFBmlBBGrdfEVkQBD -1sS0PWCLGFOQXrOWZysS9TfiRicPHtmW5gH9hOhGA97n4RwaIMXCjLVjpqvDhT7 8akYpSQSN53PyaSlo99ffgDpc8Asy0FKNVSQpCqYg6G6BFTj12tt0JTIcH5U8RnI fN8bVrcu578pDx1-bwfVkg(★2個目の"signature string") . WwogICAgewogICAgICAgICJjZXJ0c191cmkiOiAiaHR0cHM6Ly9leGFtcGxlLmNv bS9teWNlcnRzLnBlbSIgCiAgICB9LAogICAgewogICAgICAgICJhbGdvcml0aG0i OiAiUlNBLVNIQTEiLAogICAgICAgICJjZXJ0c191cmkiOiAiaHR0cHM6Ly9leGFt cGxlLm9yZy9teWNlcnRzLnBlbSIgCiAgICB9IApd(★"ascii armoured sig_params") . ewogICAgImF1ZGllbmNlIjogImh0dHBzOi8vZXhhbXBsZS1jbGllbnQuY29tL3Jl ZGlyZWN0X3VyaSIsCiAgICAib2F1dGhfdG9rZW4iOiAiYXNkZmprbHNkZmp3b0lq ZmsiLAogICAgIm5vdF9hZnRlciI6IDEyMzQ1Njc4LAogICAgInVzZXJfaWQiOiAi MTIyMyIsCiAgICAicHJvZmlsZV9pZCI6ICIxMjIzIgp9(★"ascii armoured payload")
5. Signature Verification
署名の確認方法。
秘密鍵へのアクセスについては、
1. HMAC-SHA256のときは共有秘密鍵をあらかじめやりとりしておく。
2. RSAの方は、X.509 certificateで定義されているもの。これはDiscoveryで取得 or thumbprintを使って自分たちのデータストレージから探す。
確認ロジックは、
1. JSONをパース
2. Web Token Serializationの場合、ピリオドで分割
3. "signature string" と "ascii armoured payload"をBase64 URLデコード
4. "HMAC-SHA256"の場合はclient_secretを使って署名を計算
5. "RSA-SHA256" か "RSA-SHA1"の場合は、"certs_uri"から鍵を見つけて頑張って署名を作成
感想など
これぐらいなら、どの言語でも一般的な関数で実装できそうですね。
名前載せてもらってるんだから何かコメントしないと!って思ったけど、MLのやりとりに鋭く突っ込こめるところはありません。
あえて思ったことといえば、複数の署名があるときのWeb Token Serializationですかね。
"ascii armoured sig_params"は2個の署名パラメータがまとめられていますが、"signature string"は1つずつ別なのですね。最初にこの仕様読んだとき、JSON Serializationの方とWeb Token Serializationの個数が違うのでちょっとわかりにくいような気も。しかし、良いアイディアが思いつかない。
そして、途中から、このタイミングで翻訳すればいいんじゃね?って思ったけどそれはそれで時間かかるのでまたあとで・・・
次は、「JSON Simple Encryption」を読みます!