結論
- URLでBase64を扱う場合はBase64urlを使用する。
背景
とあるデータに紐づいて発行したQRを読み込み、ユーザがどのQRを読み込んだかを一意に特定するためURLにクエリストリングとしてパラメータを埋め込む必要があった。
→ そこまで重要な情報ではないものの、平文で埋め込むのはあまりよろしくないと考えBase64でエンコードして埋め込むことにした。
試行内容
1. Base64
クエリストリングの値をBase64でエンコードして埋め込む。
https://<domain>/<function>?param=QmFzZTY044Ko44Oz44Kz44O844OJ44GZ44KL44Go6KiY5Y+344KS5ZCr44KA44OG44K544OI44OR44Op44Oh44O844K/44CC
これはBase64で使用される記号、"/" , "+" , "="
1 の3つがURI予約文字のため正しくURLが解釈されずNGです。
2. Base64 + パーセントエンコーディング(URLエンコード)
クエリストリングの値をBase64でエンコードした後、さらにパーセントエンコーディングして埋め込む。
https://<domain>/<function>?param=QmFzZTY044Ko44Oz44Kz44O844OJ44GZ44KL44Go6KiY5Y%2B344KS5ZCr44KA44OG44K544OI44OR44Op44Oh44O844K%2F44CC
一見これで問題なさそうに見えたが、パーセントエンコーディングをデコードしてからURLを叩くアプリが存在2するため、上記のBase64でエンコードしたのみの場合と同様の現象が起きるためこの方法もNG3だった。
3. Base64url
クエリストリングの値をBase64urlでエンコードして埋め込む。
https://<domain>/<function>?param=QmFzZTY044Ko44Oz44Kz44O844OJ44GZ44KL44Go6KiY5Y-344KS5ZCr44KA44OG44K544OI44OR44Op44Oh44O844K_44CC
Base64urlとは、URLとファイル名で不都合が生じないよう記号を予約文字以外の記号に置き換え、(暗黙的にデータ長が判明している場合のみ)パディングの"="
を取り除いた変形Base644です。
表.1 Base64 と Base64url の記号対応表
変換対象2進数(10進数) | Base64 | Base64url |
---|---|---|
111110(62) | + | - |
111111(63) | / | _ |
example1とexample3を比較すると、表.1の通り記号が置き換わっていることが確認できます。
なお、Base64urlへの変換関数があるかどうかは言語による様子。
まとめ
- パーセントエンコーディングをデコードしてからURLを叩くアプリが存在するため、Base64をURL上で使用する場合にはBase64urlを使用すると安全。
- Base64urlへの変換関数が実装されていないことがあるため、必要に応じて変換関数を作成する必要がある。
参考文献
- RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax
- RFC 4648 - The Base16, Base32, and Base64 Data Encodings