Base64 URL セーフエンコーディング: その概要と重要性
Base64 URL セーフエンコーディングとは何ですか?
Base64 URL セーフエンコーディング(Base64url とも呼ばれる)は、標準の Base64 の変種であり、URL やファイル名で特別な意味を持つ文字を安全な代替文字に置き換えます。標準の Base64 は 64 文字のアルファベットの一部として + と / を使用し、さらにパディング用に = を使用しますが、これら 3 つはすべて URL、クエリ文字列、ファイルパスで問題があります。
Base64url は 2 つの単純な置換でこれを解決します:
| 標準 Base64 | URL セーフ Base64 |
|-----------------|-----------------|
| + (プラス) | - (マイナス) |
| / (スラッシュ) | _ (アンダースコア) |
| = (パディング) | 省略(通常) |
なぜ標準 Base64 は URL を壊すのか
+ や / を含む Base64 エンコードされた文字列が URL に現れると、ブラウザとサーバーの動作が予測不能になります。
+ の問題
URL クエリ文字列では、+ 文字はスペースとして解釈されます。この動作は application/x-www-form-urlencoded 仕様に由来し、デコードされたデータに予期しないスペースが含まれる原因になります。
たとえば、Pj4+Pz8/Pw== のような Base64 文字列には + 文字が含まれています。これが URL パラメータ ?token=Pj4+Pz8/Pw== に現れると、サーバーは ?token=Pj4 Pz8/Pw== として認識します — + がスペースになります。
/ の問題
URL パスでは、/ 文字はパス区切り文字です。ab/CD+Ef== のような Base64 文字列には、ディレクトリレベルとして解釈される / が含まれています。これが URL セグメントに現れると、クライアントとサーバーの両方が構造を誤解釈する可能性があります。
= の問題
= 文字はクエリ文字列のキーと値のペアに使用されます。?data=SGVsbG8= の末尾の = は曖昧になる可能性があります — その = は Base64 のパディングの一部なのか、クエリパラメータの構文なのか?
パーセントエンコーディングはこれらの問題を修正できます(+ は %2B に、/ は %2F になります)が、文字列の長さを膨張させ、デバッグを難しくします。Base64url はよりクリーンなソリューションです。
Base64url の仕組み
Base64url は RFC 4648 セクション 5 で正式に定義されています。標準の Base64 とまったく同じアルゴリズムを使用します — 3 バイトが 4 文字になります — ただし、アルファベットの位置 62 と 63 で 1 文字の置換が行われます:
- アルファベットのインデックス 62:
+→-(マイナス) - アルファベットのインデックス 63:
/→_(アンダースコア)
パディング(=)は通常削除されます。デコード時に文字列の長さから推測できるためです。Base64url 文字列は、追加のエスケープなしで常に有効な URL コンポーネントです。
変換前と変換後
同じバイナリデータが両方の形式でどのように見えるかを次に示します:
Standard: Pj4+Pz8/Pw==
URL-safe: Pj4-Pz8_Pw
Base64url が使用される場所
JSON Web Token(JWT)
JWT は Base64url の最も顕著な利用者です。すべての JWT はヘッダー、ペイロード、シグネチャの 3 つの部分で構成され、それぞれが URL セーフな Base64 でエンコードされ、ドットで区切られます:
eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNqP0m2iTgCjD0
ダッシュとアンダースコアに注目してください — プラス記号やスラッシュはありません。JWT が標準の Base64 を使用していたら、Web アプリケーションで最も一般的な使用法である URL パラメータとして渡されたときに、トークンが壊れてしまいます。
OAuth と OpenID Connect
OAuth 2.0 と OpenID Connect の両方がアクセストークンと ID トークンに JWT を使用しており、Base64url エンコーディングは現代の認証の基盤となっています。認可コードフロー、インプリシットフロー、クライアントクレデンシャルフローはすべて、Base64url を使用するトークンを送信します。
Web API とクエリパラメータ
多くの REST および GraphQL API は、ページネーションカーソル、フィルター、またはエンコードされたペイロード用に、クエリパラメータで Base64 エンコードされたデータを受け入れます。Base64url により、これらのパラメータは追加の URL エンコーディングなしで正しく機能します。
実際の例 — API カーソルページネーション:
GET /api/users?cursor=MjAyNC0wMS0xNVQxMDozMDowMFo
GitHub の API は、大きな結果セットのページネーションにこの正確なパターンを使用しています。
ファイル名とファイルストレージ
Base64url 文字列は、パス区切り文字(/)を含まず、ファイルシステムを混乱させる特別な文字を含まず、Windows で無効な文字(:、*、? など)も含まないため、安全なファイル名になります。
コンテンツ配信ネットワークとキャッシュキー
CDN とキャッシュレイヤーは、しばしば Base64url エンコードされた値をキャッシュキーとして使用します。/ を含む標準の Base64 はキャッシュ名前空間に偽のディレクトリ階層を作成し、曖昧なキーにつながる可能性があります。
標準 Base64 と Base64url の間の変換
2 つの変種間の変換は、どの言語でも簡単です:
JavaScript
// Standard Base64 to URL-safe Base64
function base64ToBase64url(base64) {
return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}
// URL-safe Base64 to Standard Base64
function base64urlToBase64(base64url) {
let result = base64url.replace(/-/g, '+').replace(/_/g, '/');
// Restore padding
while (result.length % 4) {
result += '=';
}
return result;
}
Node.js
Node.js はバージョン 15.7.0 以降、ネイティブの Base64url サポートを提供します:
// Encode to Base64url
const encodedUrl = Buffer.from('Hello, world!').toString('base64url');
console.log(encodedUrl);
// Output: SGVsbG8sIHdvcmxkIQ
// Decode from Base64url
const decoded = Buffer.from(encodedUrl, 'base64url').toString('utf-8');
console.log(decoded);
// Output: Hello, world!
Python
import base64
# Encode to Base64url
encoded = base64.urlsafe_b64encode(b"Hello, world!")
print(encoded.decode())
# Output: SGVsbG8sIHdvcmxkIQ==
# Decode from Base64url
decoded = base64.urlsafe_b64decode(encoded)
print(decoded.decode())
# Output: Hello, world!
標準 Base64 と Base64url のどちらを使用すべきか
標準 Base64 を使用すべき場合:
- メール添付をエンコードする場合(MIME 標準で必要)
- HTML/CSS 埋め込み用のデータ URL を生成する場合
- URL 安全性が関係ないデータベースにデータを保存する場合
- 標準の Base64 を期待するレガシーシステムとやり取りする場合
Base64url を使用すべき場合:
- JWT トークンを作成または解析する場合
- URL クエリパラメータやパスセグメントでエンコードされたデータを渡す場合
- バイナリデータからファイル名を生成する場合
- キャッシュキーや識別子を作成する場合
- OAuth トークンや OpenID Connect を扱う場合
Base64 URL セーフエンコーディングをオンラインで試す
無料のオンライン Base64 エンコーダとデコーダを使用して、標準 Base64 と URL セーフ Base64 形式の間で変換しましょう。データを貼り付け、変種を選択し、結果を即座に取得してください。