コンテンツへスキップ
Toova
すべてのツール

Base64 エンコーディングを理解する — 完全な開発者ガイド

Toova

Base64 エンコーディングはウェブ開発のほとんどすべての領域に現れます — JWT トークン、データ URI、メールの添付ファイル、API ペイロード、暗号署名、設定ファイル。普及しているにもかかわらず、しばしば誤解されています: 開発者は時々それを暗号化と混同したり、事態を悪化させる状況で使用したりします。このガイドでは、Base64 がどのように動作するか、いつ手を伸ばすか、いつ避けるか、そして JavaScript でどのように正しく使用するかを正確に説明します。

Base64 エンコーディングとは何か (そして何でないか)

Base64 はバイナリからテキストへのエンコーディングスキームです。唯一の仕事は、任意のバイナリデータを印刷可能な ASCII 文字の文字列に変換することです。データを圧縮せず、データを暗号化せず、データを検証しません。これは純粋に表現の変換です — null バイト、制御文字、またはテキストベースのプロトコルを壊す値を含む可能性のあるバイトを取り、安全な文字セットに変換します。

名前は、エンコーディングアルファベットとして使用される 64 個の印刷可能な文字から来ています: A–Z (26 文字)、a–z (26 文字)、0–9 (10 文字)、加えて +/ (2 文字)。= 文字はパディングに使用されます。各文字位置で 64 の可能な値があり 2^6 = 64 であるため、各 Base64 文字は元のデータの正確に 6 ビットをエンコードします。

Base64 はどのように動作するか — 「Hello」を段階的に

Base64 を理解する最良の方法は、具体例を追うことです。文字列 Hello をエンコードしてみましょう。

ステップ 1: バイトに変換

Hello の各文字は ASCII コードにマッピングされ、その後バイナリ (バイトごとに 8 ビット) で表現されます:

H  e  l  l  o
72 65 6C 6C 6F   (ASCII / 16 進)
01001000 01100101 01101100 01101100 01101111   (バイナリ)

ステップ 2: 6 ビットチャンクにグループ化

すべてのビットを連結します: 0100100001100101011011000110110001101111 (40 ビット)。Base64 は一度に 3 バイト (24 ビット) を処理し、それらを 4 つの Base64 文字 (4 × 6 = 24 ビット) にマッピングします。40 ビットを 6 ビットチャンクにグループ化し、最後のグループをゼロでパディングして埋めます:

010010 000110 010101 101100 011011 000110 1111
18     6      21     44     27     6      (最後のグループを 6 ビットにパディング: 111100 = 60)

ステップ 3: Base64 アルファベットにマップ

各 6 ビット値は Base64 アルファベットの文字にマッピングされます (A=0、B=1、... Z=25、a=26、... z=51、0=52、... 9=61、+=62、/=63)。5 バイトは 3 の倍数ではないため、1 つの = パディング文字が追加されます:

インデックス: 18  6   21  44  27  6   60
文字:          S   G   V   s   b   G   8
結果: SGVsbG8=   (= はパディング)

結果

"Hello" → "SGVsbG8="

これを Toova Base64 エンコーダー/デコーダーで即座に検証できます — Hello を貼り付け、エンコードをクリックすると、SGVsbG8= が得られます。それを反転するにはデコードをクリックします。

33% のサイズオーバーヘッド

Base64 エンコーディングは常にデータサイズを約 33% 増加させます。計算は単純です: 入力の 3 バイト (24 ビット) が 4 つの Base64 文字 (4 × 6 ビットグループでエンコードされた 24 ビット) を生成します。これは 4/3 の比率、つまり 33.3% のオーバーヘッドです。パディング文字を追加すると、入力長によって真のオーバーヘッドは 33% から 36% の間です。

これはパフォーマンスに大きく影響します。HTML に Base64 データ URI として埋め込まれた 1 MB の画像は、約 1.37 MB になります。すべてのバイナリペイロードを Base64 でエンコードする API は、必要以上に 33% 多くのデータを送信します。短いトークンやチェックサムのような小さな値では、オーバーヘッドは無視できます。大きなファイルでは、実際のコストです。

URL セーフバリアント

標準 Base64 は、最後の 2 つのアルファベット文字として +/ を使用します。両方とも URL で問題があります:

  • + はクエリ文字列でスペース文字としてデコードされる
  • / は URL のパスセパレーター

URL セーフ Base64 (RFC 4648 セクション 5 で定義された Base64url とも呼ばれる) は、+- に、/_ に置き換えます。一部の URL パーサーによっても誤解される可能性があるため、URL セーフコンテキストでは通常パディング (=) が省略されます。

JWT トークンはパディングなしの Base64url を使用します。JWT ヘッダーやペイロードを手動でデコードするときは、文字置換と欠落したパディングの両方を処理する必要があります。JavaScript でその方法は次のとおりです:

// URL セーフ Base64 (+ を - に、/ を _ に置き換え)
function toBase64Url(base64) {
  return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}

function fromBase64Url(base64url) {
  const padded = base64url.padEnd(
    base64url.length + (4 - base64url.length % 4) % 4,
    '='
  );
  return atob(padded.replace(/-/g, '+').replace(/_/g, '/'));
}

Toova の Base64 エンコーダー/デコーダーは、単一のトグルで標準と URL セーフの両方のバリアントをサポートします。

JavaScript での Base64

ブラウザ: btoa() と atob()

ブラウザは 2 つの組み込み関数を提供します: btoa() (バイナリから ASCII、つまりエンコード) と atob() (ASCII からバイナリ、つまりデコード)。混乱する名前順にもかかわらず、それらは 10 年以上ブラウザで利用可能です。

// ブラウザ — atob / btoa (文字列のみ、ASCII セーフ)
const encoded = btoa("Hello");
console.log(encoded); // "SGVsbG8="

const decoded = atob("SGVsbG8=");
console.log(decoded); // "Hello"

重要な制限: btoa() は Latin-1 範囲 (コードポイント 0–255) の文字を持つ文字列のみを受け入れます。絵文字や CJK 文字のような Unicode 文字を含む文字列を渡すと、DOMException をスローします。任意のバイナリデータをエンコードするには、まず Uint8Array に変換します:

// ブラウザ — 任意のバイナリをエンコード (Uint8Array)
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
const encoded = btoa(String.fromCharCode(...bytes));
console.log(encoded); // "SGVsbG8="

Unicode 文字を含む可能性のある任意の文字列をエンコードするには、推奨されるモダンなアプローチは、最初に TextEncoder を使って Uint8Array を取得し、上記のようにエンコードすることです。

Node.js: Buffer

Node.js は Buffer クラスを提供し、バイナリデータを正しく処理し、Base64 と Base64url を含む複数のエンコーディングをサポートします:

// Node.js — Buffer (バイナリを安全に処理)
const encoded = Buffer.from('Hello').toString('base64');
console.log(encoded); // "SGVsbG8="

const decoded = Buffer.from('SGVsbG8=', 'base64').toString('utf8');
console.log(decoded); // "Hello"

// Node.js での URL セーフバリアント
const urlSafe = Buffer.from('Hello').toString('base64url');
console.log(urlSafe); // "SGVsbG8" (パディングなし)

base64url エンコーディングオプション (Node.js 16 以降で利用可能) は、文字置換とパディング削除を自動的に処理し、変換を手動で行うよりはるかに簡単にします。

大きなバイナリファイルを処理する必要があるブラウザ環境では、FileReader.readAsDataURL メソッドが、すべてを一度にメモリにロードせずにファイルを Base64 データ URI としてエンコードします。

いつ Base64 を使うか

テキストのみのプロトコルでのバイナリデータの埋め込み

Base64 の元のユースケースは、7 ビット ASCII テキストのみをサポートするプロトコルである SMTP でのバイナリメール添付ファイルのエンコーディングでした。生のバイトを処理できない形式にバイナリデータを含める必要があるあらゆる場所に同じ原則が適用されます: JSON API ペイロード、XML ドキュメント、HTML 属性、CSS 値、HTTP ヘッダー。

小さなアセットのためのデータ URI

CSS と HTML は、画像、フォント、SVG を Base64 データ URI として埋め込むことを許可します。これにより、アイコンのような小さなアセットの HTTP 往復が排除され、重要な above-the-fold 画像のための未スタイルコンテンツのフラッシュが排除されます。

<!-- Base64 データ URI としてのインライン SVG アイコン -->
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0c..." alt="icon" />

<!-- インライン CSS 背景 -->
.icon {
  background-image: url("data:image/png;base64,iVBORw0KGgo...");
}

トレードオフ: Base64 データ URI は、それらを含む HTML/CSS ファイルから別々にキャッシュできません。画像が変わらないが周囲の HTML が変わる場合、ブラウザはページ再読み込みごとに画像データを再ダウンロードします。データ URI は、往復の排除がキャッシュペナルティを上回る、小さなアセット (理想的には 4 KB 未満) にのみ使用してください。

JSON または URL パラメーターのバイナリデータのエンコーディング

JSON はテキスト形式です — 生のバイナリバイトを直接表現できません。API がバイナリデータ (画像サムネイル、暗号署名、圧縮データ) を送信する必要があるとき、Base64 が JSON ペイロードに含めるための標準的な方法です。同様に、URL クエリパラメーターでバイナリデータを渡す必要がある場合、Base64url エンコーディングは、データが破損なくパーセントエンコーディングを通過することを保証します。

JWT とその他のトークン形式

JWT トークンは Base64url を使用してヘッダーとペイロードセクションをエンコードします。これにより、トークンは HTTP ヘッダー、Cookie、または URL パラメーターで渡せる印刷可能な URL セーフな文字列になります。エンコーディングはセキュリティのためではありません (ペイロードはトークンを持つ誰でも読める) — それは純粋に安全な送信のためです。

いつ Base64 を使わないか

セキュリティや機密性

Base64 はゼロセキュリティを提供します。ミリ秒単位で簡単に可逆です。パスワード、API キー、または機密設定値を「難読化」するために使用しないでください。Base64 文字列を見る開発者は誰でもすぐにデコードします。機密性が必要な場合は、暗号化を使用してください。

パスワード保存

Base64 でエンコードされたパスワードを保存することは、平文で保存することと同じです — エンコーディングは即座に可逆です。パスワードは bcrypt、Argon2、scrypt のような適切なパスワードハッシュ関数でハッシュ化する必要があります。

大きなバイナリファイル

10 MB のファイルを Base64 としてエンコードすると、13.7 MB の文字列が生成されます。それをデータベース列に保存したり、それを通して検索したり、API 経由で送信したりすると、毎回 33% のオーバーヘッドを支払います。大きなバイナリデータには、専用のバイナリストレージを使用します: データベース BLOB/BYTEA 列、S3 や GCS のようなオブジェクトストレージ、またはバイナリを直接ストリーミングします。

バイナリを直接使用できる状況

プロトコルや形式が生のバイナリをサポートする場合 — たとえば、バイナリメッセージタイプの WebSocket、multipart/form-data HTTP アップロード、またはバイナリファイル形式 — バイナリを直接使用します。Base64 は、輸送媒体が本当に生のバイトを処理できないときにのみ必要です。

よくある落とし穴

エンコーディングと暗号化の混同

これは最も一般的な間違いです。Base64 は可視です。これはセキュリティメカニズムではありません。「パスワードはセキュリティのために Base64 エンコードされて保存されている」のようなコードコメントは、コードレビューで捕捉されるべき深刻な誤解を示しています。

Unicode 文字列での btoa() の使用

コードポイントが 255 を超える文字を含む文字列に対して btoa() を呼び出すと、DOMException: Failed to execute 'btoa': The string to be encoded contains characters outside of the Latin1 range がスローされます。Unicode 文字を含む可能性のある文字列をエンコードする前に、常に TextEncoder を介して Uint8Array に変換します。

デコード時のパディングを忘れる

Base64 文字列は 4 の倍数の長さを持つ必要があります。Base64 文字列がパディングなしで生成された場合 (URL セーフエンコーディングで一般的)、デコードする前に正しい数の = 文字を追加する必要があります。長さ n の Base64 文字列には (4 - n % 4) % 4 パディング文字が必要です。これを忘れると、診断が難しいデコードエラーが発生します。

二重エンコーディング

Base64 文字列自体は有効な ASCII であるため、btoa(btoa(data)) はエラーなく動作しますが、二重エンコードされた出力を生成します。複数の層のシリアル化 (たとえば、JSON 内の JSON) を介して Base64 値を渡すとき、同じデータを 2 回エンコードしやすいです。常にエンコードした正確な回数だけデコードしてください。

クイックリファレンス: 実践での Base64

コードを書かずにブラウザでエンコードおよびデコードするには、Toova Base64 エンコーダー/デコーダーがブラウザ内で完全に動作します — サーバー往復なし。標準と URL セーフのバリアント、バイナリファイルをエンコードするためのファイルアップロード、デコードされたデータのテキストと 16 進の両方の出力をサポートします。

URL 内のエンコードされたコンテンツを扱う場合、URL エンコーダー/デコーダーは Base64 とは別にパーセントエンコーディングを処理します。HTML エンティティには、HTML エンティティ変換ツールが HTML コンテキストで文字エスケープを処理します。これらは異なるエンコーディングスキームです — それぞれが特定のユースケースを持っています。

Base64 の標準リファレンスは RFC 4648 で、標準 Base64 (セクション 4)、Base64url (セクション 5)、Base32 (セクション 6–7) を定義しています。btoa()atob() ブラウザ API については、MDN の btoa() ドキュメントがブラウザ互換性と Unicode 制限を詳細にカバーしています。

まとめ

Base64 エンコーディングは、64 文字のアルファベットを使ってバイナリデータを印刷可能な ASCII に変換します。データサイズを 33% 増加させ、完全に可逆で、セキュリティを提供しません。テキストベースの形式にバイナリデータを埋め込む必要があるときに使用します — JSON ペイロード、HTML データ URI、JWT トークン、メールの添付ファイル、URL パラメーター。セキュリティが必要な場合、トランスポートがバイナリを直接サポートする場合、または 33% のオーバーヘッドが大規模に重要な場合は避けてください。

Base64 が何であるか — そして何でないか — を理解することで、最も一般的な間違いを防ぎます: セキュリティに使用すること、大きなファイルに不必要に適用すること、そして URL エンコーディングや HTML エンティティのような他のエンコーディングスキームと混同すること。各エンコーディングスキームは特定の問題を解決します。Base64 は正確に 1 つを解決します: バイナリデータをテキストのみのチャネルに対して安全にすることです。

エンコードまたはデコードする準備ができましたか?Toova Base64 エンコーダー/デコーダーをお試しください — テキストを貼り付けるかファイルをドロップし、標準または URL セーフを切り替え、結果をコピーします。アカウントなし、サーバーなし、制限なし。