JSON Simple Sign 1.0 draft 01を読みながら書いたメモ

今日は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」を読みます!