PASETOトークン解剖 — 文字列からバイトまで
PASETOトークンがワイヤー上にどうレイアウトされているか、各セグメントがどうエンコードされているか、署名や認証タグがペイロード内のどこにあるかの詳細解説。
詳細な説明
PASETOトークンのレイアウトをバイト単位で理解することは、発行と検証のバグをデバッグする最速の方法です。
トップレベル構造:
vN.purpose.<payload-segment>[.<footer-segment>]
ドット区切りのパートが3つまたは4つあります。最初の2つ — vN と purpose — はプレーンASCIIで、それ以外はすべてパディングなしのBase64urlです。
ヘッダーセグメント:
最初の2つのパートを合わせてヘッダー文字列を形成し、これは事前認証エンコーディング(PAE)経由で暗号操作にバインドされます。例:v4.public、v4.local、v3.public、v2.local。JWTのようなJSONヘッダーはなく、ヘッダーはバージョンと用途文字列の文字通りの連結です。
publicトークンのペイロードセグメント:
Base64urlデコード後、v*.public のペイロードセグメントはUTF-8 JSONメッセージに署名バイトを続けたものです。署名長:
- v1.public:256バイト(RSA-PSS-2048)
- v2.public:64バイト(Ed25519)
- v3.public:96バイト(ECDSA P-384、生のR||S)
- v4.public:64バイト(Ed25519)
JSONを抽出するには、セグメントをデコードして末尾Nバイトを切り捨てます。
localトークンのペイロードセグメント:
v*.local の場合、Base64urlデコード後のレイアウトは:nonce、暗号文、タグ — を連結したものです。長さ:
- v1.local:32バイトのnonce、暗号文、48バイトのHMAC-SHA384タグ
- v2.local:24バイトのnonce、暗号文、16バイトのPoly1305タグ
- v3.local:32バイトのnonce、暗号文、48バイトのHMAC-SHA384タグ
- v4.local:32バイトのnonce、暗号文、32バイトのBLAKE2bタグ
暗号文はちょうど平文JSONの長さです — パディングなし。
フッターセグメント:
存在する場合、フッターは単にBase64urlエンコードされた生バイトです。PASETOは構造を強制せず、アプリケーションが定義します。慣例的に、JSONフッターが一般的です。
事前認証エンコーディング(PAE):
これはセグメント間でバイトを移動できないようにする魔法の接着剤です。PAEはアイテム数を連結し、各アイテムについてリトルエンディアン長とそのバイトを続けます。署名/タグはPAE(header, body, footer)(v3/v4では暗黙アサーションも)に対して計算されます。任意のセグメントを改ざんするとPAEが変わり、検証が壊れます。
ユースケース
カスタムPASETOライブラリを構築する開発者がこの解剖を使って、JSONをアプリケーションに渡す前にv4.publicペイロードから末尾64バイトの署名を正しく切り出すパーサーを書きます。