開発者ツール · Base64 エンコーダーおよびデコーダー
Base64 パディングの説明: = 記号の意味とそれらが必要な場合
· 仕組み
base64 エンコード 開発者ワークフロー
Base64 文字列の末尾の = は装飾ではありません。これは、最後のグループが何バイト不足だったかを記録します。この記事では、算術演算、一部の文字列に何もない理由、およびパディングの欠落についてデコーダーが意見を異にする理由について説明します。
正常に見えたトークンからの「不正なパディング」例外 - デコードの失敗とその後ろの 1 つまたは 2 つの欠落文字
Base64 デコーダーが不正なパディングを報告すると、文字列は完全に見えますが、構造上のエラーが発生します。等号は表面的なものではありません。各等号は、最終グループが不足したバイト数をエンコードするため、デコーダは実際のデータがいつ終了したかを正確に知ることができます。これらの = 記号と、厳密なデコーダがこれらの = 記号のない文字列を拒否する理由を理解すると、謎のエラーが予測可能な算術演算に変換されます。 JWT セグメントには = が 1 つある場合もあれば、ない場合もあれば、2 つある場合もあります。 API 応答はパディングなしで正常に終了する場合があります。
これらは、実装のバリエーションではなく、意図的な選択を表します。デコードプロセスでは機械的なパディングは必要ありません。パディングは出力を明確にするために存在します。長さに関するメタデータのない Base64 文字列のみが与えられると、デコーダーはパディングを読み取り、データがどこで終了したかを正確に認識します。 Base64 は、3 バイトのグループを 4 つの文字にエンコードします。 3 バイトは 24 ビットで、4 つの 6 ビット インデックスに完全に再グループ化されます。それぞれ 64 Base64 シンボルの 1 つを選択します。入力が 3 の倍数ではない場合、エンコーダーは残り物に直面します。1 バイトまたは 2 バイトを 3 で均等に割ることはできません。
3 バイトのグループ、4 文字のブロック — 3 を法とする入力長によって = 記号が 0、1、または 2 つ表示されるかどうかが決まる理由
エンコーダーは、ビットを最初のインデックスにシフトして、最終インデックスをゼロのままにして、これらのグループをパディングします。これを意図的にマークするには、= 記号を追加します。完全なグループの場合は 0、2 バイトの末尾の場合は 1 つ、1 バイトの末尾の場合は 2 つです。算術演算は決定的です。入力長をバイト単位で知ることで、パディングをすぐに計算できます。 1 バイトは 2 つの Base64 文字と 2 つの = を生成します。 2 バイトは 3 文字と 1 つの = を生成します。 3 バイトはパディングなしで 4 バイトを生成します。
3 バイトの倍数ではない入力にはパディングが含まれます。複数の場合はそうではありません。これは選択ではなく、算術です。パディングのない文字列は 3 バイトを表す必要があります。 1 つの等しい文字列は 2 を表す必要があります。パディングは入力長を 3 を法としてエンコードします。 3 つの入力 (単一 a、ペア ab、三重 abc) の変換を調べます。 ASCII a はバイト 0x61 です。 Base64 はこれを 0x61 00 00 としてエンコードし、6 ビットのグループに再グループ化します。
パディング ビットの内容と、厳密なデコーダーがパディング ビットをチェックする理由 — ゼロでなければならないビット、および標準エンコーディングの意味
インデックス 24、4、0、0 は Y、E、A、A にマップされます。2 つのグループがパディングされていたため、エンコーダーは 2 つの = 記号を追加し、YQ== を生成します。 ab の場合、バイト 0x61 0x62 は 0x61 0x62 00 になります。ビットはインデックス 24、22、8、0、出力 YWI= に再グループ化されます。 abc の場合、バイトはインデックス 24、22、9、35 に再グループ化され、パディングなしで YWJj を出力します。パディングは任意ではありません。ビット レイアウトから外れてしまいます。 Base64 文字列をデコードすると、デコーダは各文字を読み取り、その 6 ビット インデックスを検索し、ビットをバイトにパックします。
YQ== の場合、文字 Y、E、A、A はビットにアンパックされます。 8 ビット バイトに再グループ化すると、1 バイトの 0x61 が得られます。デコーダはパディング ビット (後続のゼロ) を破棄し、1 バイトを報告します。厳密なデコーダは、パディング ビットが実際にゼロであることをチェックします。そうでない場合、入力は正規ではありません。つまり、誰かが異なるビット レイアウトを使用してエンコードされ、デコードがあいまいであることを意味します。パディングを完全に省略したシステムでは、意図的なトレードオフが行われます。 JWT セグメントは、パディングなしで Base64url を使用し、予想される出力長を知っているか推測するコンシューマーに依存します。
作業例: 'a'、'ab'、および 'abc' を手動でエンコードする — 3 つの入力、3 つのパディング結果をビットごとに表示
RFC 4648 は、パディングが存在しないことを許可しますが、存在する場合はそれを受け入れるようにデコーダーに指示します。コード ライブラリは異なります。失われたパディングを復元して続行するものもあります。他の人は失敗するでしょう。デコードに失敗したトークンに遭遇した場合、適切な数の = 記号を追加すると、問題が解決されることがよくあります。必須の = 記号は、文字列の長さのモジュロ 4 に応じて、常に 0、1、または 2 です。 Base64 文字列の長さが 4 の倍数でない場合は、パディングが確実に欠落しているか破損しています。
5 の長さは有効な Base64 にはできません。完全な各文字は 6 ビットをエンコードするため、4 文字は 24 ビット (3 バイト) をエンコードし、5 文字は 30 ビットをエンコードします。これは 8 の倍数ではないため、バイトになることはできません。デコーダはこれを拒否するか、パディングを追加する必要があります。長さが 2 モジュロ 4 の場合、= を 2 つ追加します。 3 モジュロ 4 の場合、= を 1 つ追加します。 0 を 4 で割った場合は、何も追加しません。長さ 3 の文字列には、必要な = がありません。 1 つ追加すると、デコード前に有効になります。
一部のシステムがパディングを完全に削除する理由 — JWT セグメントと = を省略した URL セーフ トークン、および長さからパディングを復元する方法
パディングが残っていると、2 つのパディングされた Base64 文字列を連結すると壊れます。 2 つの別々のエンコードを直接結合すると、デコード アルファベットを破壊する浮遊パディング文字が生成されます。これが、一部のシステムが連結前にパディングを削除する理由です。ドットで結合された 3 つの Base64url セグメントで構成されるトークンにはセグメント内にパディングがないため、連結が簡単になります。パーツから Base64 値を構築する場合は、各パーツがパディングされているかどうかを確認し、操作の前に一貫してパディングを削除または追加してください。
Base64 エンコーダーおよびデコーダーは、デフォルトでパディングを必要とする RFC 4648 を適用します。テキストを入力して Base64 出力を要求すると、ツールはパディングされた結果、つまり正規形式を生成します。パディングのない Base64 が表示され、それをデコードしたい場合は、デコーダが不足しているパディングを受け入れるかどうかを確認してください。このツールは、パディングされた入力とパディングされていない入力の両方を受け入れ、元のバイトを正しく復元します。デバッグの場合、長さを法 4 で数えることによってパディングが削除されたかどうかがわかり、式によってどのようなパディングが存在する必要があるかがわかります。
よくある間違い: トリミング = 空白であるかのようにする、または 2 つの埋め込まれた文字列を連結する - それぞれがどのようにデコードを破壊するか
Base32 と Base16 (16 進数) には、RFC 4648 セクション 6 および 7 で定義された異なるパディング ルールがあります。 Base32 は = を使用しますが、最後のグループは、入力長のモジュロ 5 に応じて、2、4、5、7、または 8 文字になります。 16 進数にはパディングは必要ありません。常に 1 バイトを剰余なしで 2 文字にマップします。 MIME Base64 のラッピングはパディングに影響します。76 列でラップされた文字列は、最後の数行後でもまだパディングを持っています。
Base64 のパディングを理解するには、ビット レイアウトと入力長のモジュロ 3 を理解する必要があります。算術を理解すると、パディングは暗記するルールではなく、直接的な結果になります。パディングは導出可能であり、魔法ではありません。
これでカバーされないもの — Base32 および Base16 のパディング ルール、および MIME 行の長さの規則
任意の長さの Base64 文字列を指定すると、文字数を 4 で割って余りを取り、対応する数の = 記号を追加することで、標準的な埋め込み形式を復元できます。これが、missing = が修正可能であり、厳密なデコーダが寛容である理由です。パディングには情報 (入力が 3 つのケースのどの分岐に該当するか) が含まれますが、その情報は長さだけから計算できます。
Base64 エンコーダーとデコーダーはパディングされた出力をすぐに表示するため、デコードされたバイトを元のテキストと比較し、ラウンドトリップが機能していることを確認できます。 Base64 および関連エンコーディングは、ビットを異なる文字幅に再グループ化する原理を拡張します。 RFC 4648 は 3 つすべてを規定しており、1 つを理解すれば他の部分も概念的に単純になります。重要な洞察は、エンコードは純粋なビット操作であるということです。アルファベットのサイズを選択し、それに応じてビットをグループ化し、テーブル内の各グループを検索します。
要点: パディングは導出可能であるため、欠落している = は修正可能です — Base64 エンコーダーとデコーダーが、エンコードしたテキストのパディングされた正規形式をどのように表示するか
デコードは逆に行われます。各文字を検索し、ビットを抽出し、それらを再グループ化し、バイトを書き込みます。この決定的な双方向マッピングが、Base64 がすべてのプラットフォームと言語で確実に動作する理由です。エンコードおよびデコードにおけるエラーは、多くの場合、パディングの誤解やアルファベットの違いに起因します。デコードがパディング エラーで失敗した場合は、デコーダが正規の Base64 (厳密にパディング) を期待しているか、バリアントを受け入れているかを確認してください。文字エラーで失敗した場合は、入力がbase64urlであり、デコーダが標準のBase64を想定しているかどうかを確認してください。
Base64 エンコーダーとデコーダーは両方のアルファベットを受け入れ、一貫してパディングを検証するため、手動で計算されたサンプルは即座に検証できます。エンコードをデコードしてテストすることは、運用上の問題が発生する前に間違いを発見する最も確実な方法です。