Base64URL を Base64 に変換する手順
- Base64URL を 入力 · Base64URL に貼り付けます。パディングはあってもなくてもよく、入力に標準の
+や/が含まれていても問題ありません。 - 出力 · Base64 に標準の Base64 が表示されます。
-と_は+と/に変わり、パディングも復元されています。 - 出力の下では パディング(=) が既定でオンになっています。折り返し を使うと、結果を PEM 用に 64 文字、MIME 用に 76 文字で改行できます。
- 出力をコピー を押します。逆方向は Base64 → Base64URL の切り替えか、Base64 から Base64URL へ を使います。
付け足すパディングの数
Base64 は 4 文字単位のグループで動作します。Base64URL では通常、最後のグループを埋める = が省略されるので、長さを見れば何個戻せばよいかがわかります。
| 長さを 4 で割った余り | 付け足すパディング | 例 |
|---|---|---|
| 0 | なし | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9(36 文字) |
| 2 | == | PDw_Pz8-Pg(10 文字)は PDw/Pz8+Pg== になる |
| 3 | = | eyJyb2xlIjoiYWRtaW4-In0(23 文字)は eyJyb2xlIjoiYWRtaW4+In0= になる |
| 1 | 無効 | 余った 1 文字では 1 バイト全体を表せない |
よく知られたペイロードの例 eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ は 70 文字で、余りは 2 なので、末尾に == を付けた同じ文字列になります。詳しい理屈は パディングの解説 をご覧ください。
標準の Base64 が必要になる理由
多くのデコーダーは標準のアルファベットしか受け付けず、Base64URL を渡すとそれぞれ違った形で失敗します。
- GNU coreutils の
base64 -dは、最初の-や_までにデコードできた分を出力してから、base64: invalid inputを表示します。 - Java の
Base64.getDecoder()はIllegalArgumentExceptionを投げます。URL セーフな入力にはBase64.getUrlDecoder()を使います。 - .NET の
Convert.FromBase64Stringは、-、_、=の欠落に対してFormatExceptionを投げます。 - Python の
base64.b64decodeは危険です。既定では、標準のアルファベット以外の文字をエラーを出さずに捨ててしまいます。b64decode("PDw_Pz8-Pg==")はb'<<???>>'ではなくb'<<\x0f\xcf\xc3\xe0'を返します。
トークンを扱うコードでは、最後のケースをテストしておく価値があります。例外が出ないまま誤ったバイト列ができると、たいていずっと後になって、署名検証の失敗やデータの破損として表面化します。
コードで Base64URL を Base64 にする
import base64
def b64url_to_bytes(s: str) -> bytes:
return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))
b64url_to_bytes("PDw_Pz8-Pg") # b'<<???>>'
base64.b64encode(b64url_to_bytes("PDw_Pz8-Pg")).decode() # 'PDw/Pz8+Pg=='
-len(s) % 4 は不足している = の数で、有効な入力なら 0、1、2 のいずれかです。urlsafe_b64decode にはパディングが必要なので、呼び出しの前に付け足しています。
function b64urlToB64(s) {
const b = s.replace(/-/g, "+").replace(/_/g, "/");
return b + "=".repeat((4 - (b.length % 4)) % 4);
}
b64urlToB64("PDw_Pz8-Pg"); // 'PDw/Pz8+Pg=='
Node.js なら、Buffer.from(s, "base64url").toString("base64") の 1 回の呼び出しで同じことができます。各言語の標準ライブラリにある URL セーフなデコーダーについては、Python、Java、C# のページをご覧ください。
よくある問題
- 「最後の文字グループが不完全です」。 長さを 4 で割った余りが 1 です。文字列の一部が失われています。改行の位置や、URL が途中で切れたことが原因であることが多いです。
- 入力に
.がある。 JWT は 3 つの Base64URL セグメントをドットでつないでいます。セグメントを 1 つずつ変換してください。JWT デコーダー ならトークン全体をそのまま読めます。 - 文字列に
%3Dがある。 値が Base64URL のうえにさらにパーセントエンコードされています。先に URL デコード でデコードしてください。
よくある質問
Base64URL にパディングを付け直すには?
末尾に = を足して 4 文字の倍数にします。余りが 2 なら 2 つ、3 なら 1 つです。余りが 1 になることは有効なデータではありえません。この変換ツールなら自動で処理します。
JWT に base64 -d を使うと失敗するのはなぜですか?
GNU の base64 -d は標準のアルファベットしか知らず、最初の - や _ で invalid input を出して止まります。先にここでセグメントを変換するか、URL セーフのアルファベットを読める basenc --base64url -d を使ってください。
文字列が 1 文字多い場合はどうなりますか?
長さを 4 で割った余りが 1 になる Base64URL 文字列は、途中で切れているか余分な文字が入っています。変換ツールは最後のグループが不完全であることを報告するので、値のコピー方法を確認してください。
JWT を読むには標準の Base64 が必要ですか?
このサイトなら不要です。JWT デコーダー と Base64URL デコーダー は Base64URL を直接読めます。標準の Base64 に変換するのは、ほかのツールやライブラリがその形式しか受け付けない場合です。