Base64 に関して知っておくべきすべて

> 本記事は元々 [blog.logto.io](https://blog.logto.io/ja/all-about-base64) に掲載されたものです。



ソフトウェア開発の世界で、Base64 は頻繁に言及される概念ですが、常に完全に理解されているわけではありません。この分野の新人であっても、経験豊富な開発者であっても、Base64 を深く理解することで、データのエンコーディングや送信を簡単に処理できるようになります。Base64 の定義と起源から実際の応用と使用法まで、すべての側面を探っていきましょう。

## Base64 とは？

Base64 は 64 の印刷可能な文字を使用してバイナリデータを表現するエンコーディング方法です。これらの 64 文字には以下が含まれます：

- `A-Z`, `a-z`, `0-9` （62 の文字と数字）
- `+` と `/` （2 つの特殊文字）
- `=` （パディングに使用される）

日常の開発作業では、Base64 は至るところにあります。以下のシナリオで見かけたことがあるかもしれません：

- HTML に小さな画像やアイコンを埋め込む
- API レスポンスでバイナリデータを送信する
- メールの添付ファイルをエンコードする

たとえば、次のような HTML コードを見たことがあるかもしれません：

```html
<img
  src="data:image/png; base64, data:image/png; base64, iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
  alt="Red dot"
/>
```

ここでの長い文字列は、Base64 でエンコードされた小さな画像です。

## なぜ Base64 なのか？

Base64 の存在理由を理解するには、コンピュータ開発の初期の歴史を振り返る必要があります。

コンピュータネットワークの初期の頃、大多数のシステムは印刷可能な [ASCII](https://en.wikipedia.org/wiki/ASCII) 文字しか扱うことができませんでした。ASCII エンコードは 7 ビットのバイナリデータのみを使用し、128 文字を表現します。これは英語のテキストを処理するには問題ありませんが、バイナリデータ（たとえば画像や音声ファイル）を送信する際には問題が発生します。

異なるシステムが特定の制御文字を異なる方法で解釈し、送信中にデータが破損する可能性があります。たとえば、システムによっては改行を LF （ラインフィード）から CR （キャリッジリターン）+ LF に変更することがあり、これはバイナリデータには致命的です。

この問題を解決するため、人々は任意のバイナリデータを安全に送信できる文字に変換する方法を模索し始めました。これが Base64 エンコーディングの起源です。

実際には、Base64 よりも前に Base16 （16 文字使用）や Base32 （32 文字使用）といったエンコーディング方法がありました。しかし、Base64 がエンコード効率と実用性のバランスが最も良いため、最も広く使用されるようになりました。

## Base64 エンコーディングの仕組み

Base64 の核心的なアイデアは、3 バイト（24 ビット）のバイナリデータを 4 つの印刷可能な文字にエンコードすることです。

具体例を通じてこのプロセスを理解してみましょう。

「Logto」という文字列をエンコードしたいとしましょう：

1. まず、「Logto」を ASCII コードに変換します：

- `L`: `76` （`01001100`）
- `o`: `111` （`01101111`）
- `g`: `103` （`01100111`）
- `t`: `116` （`01110100`）
- `o`: `111` （`01101111`）

2. これらのバイナリ数値を連結します（合計 5 バイト、40 ビット）：
   `0100110001101111011001110111010001101111`

3. これらのビットを 6 ビットのグループに分けます（最後のグループには 4 ビットしかありません）：
   `010011` | `000110` | `111101` | `100111` | `011101` | `000110` | `1111`

4. 最後のグループには 4 ビットしかないため、6 ビットにするために末尾に 2 つの 0 を追加します：
   `010011` | `000110` | `111101` | `100111` | `011101` | `000110` | `111100`

5. 各 6 ビットのグループを 10 進数に変換します：
   `19` | `6` | `61` | `39` | `29` | `6` | `60`

6. [Base64 エンコーディング表](https://en.wikipedia.org/wiki/Base64#Base64_table_from_RFC_4648) に従って、これらの数値を対応する文字に変換します：
   `T` | `G` | `9` | `n` | `d` | `G` | `8`

7. 最後に、Base64 エンコーディングは常に 3 バイト（24 ビット）のバイナリデータを 4 つの印刷可能な文字にエンコードします。「Logto」はバイナリで 5 バイトになりますので、最初の 3 バイトは `TG9n` に、最後の 2 バイトは `dG8` にエンコードされます。そのため、最後に 1 つの `=` をパディング文字として追加する必要があります。

このようにして、「Logto」の Base64 エンコーディングは `TG9ndG8=` です。

Node.js では、次のようにして Base64 エンコーディングを生成できます：

```javascript
const text = 'Logto';
const base64 = Buffer.from(text).toString('base64');
console.log(base64); // Output: TG9ndG8=
```

この例は Base64 エンコーディングのいくつかの重要な特徴を示しています：

- 入力の 3 バイトごとに 4 つの出力文字が生成されます。
- 入力バイト数が 3 の倍数でない場合、「=」パディング文字が使用されます。この例では、5 バイトの入力によって 7 つの Base64 文字と 1 つのパディング文字が生成されます。
- パディング文字によって、元のデータの正確なバイト数がわかります：
  - パディングなし：元のデータは 3 バイトの倍数です
  - `=` が 1 つ：エンコード前に原データに 2 ビットの 0 が追加されました
  - `=` が 2 つ：エンコード前に原データに 4 ビットの 0 が追加されました

## Base64 を使用するタイミングと理由

Base64 は特に次のようなシナリオで有用です：

1. HTML に小さなバイナリデータ（小さな画像やアイコンなど）を埋め込む
2. テキストのみ送信できるプロトコルでバイナリデータを送信する
3. 特殊文字の使用が制限されているシステムでデータを送信する
4. 簡単なデータ難読化（注意：これは暗号化ではありません！）

Base64 を使用する主な利点は次の通りです：

- クロスプラットフォームの互換性が高い：Base64 エンコードされたデータは、ASCII をサポートする任意のシステムで正しく解析できます
- 場合によっては送信効率を向上させる：例えば、送信されるデータに大量の繰り返しバイナリパターンが含まれている場合

標準的な Base64 のほかに、知っておくべきいくつかのバリアントがあります：

- URL 安全な Base64：`+` を `-` に、`/` を `_` に置き換え、`=` を削除します。このエンコードは追加のエンコードなしで URL で直接使用できます。

```javascript
const base64 = 'TG9ndG8=';
const urlSafe = base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
console.log(urlSafe);
```

## Base64 の制限と考慮事項

Base64 は有用ですが、いくつかの制限もあります：

1. データの膨張：Base64 エンコードはデータ量を約 33% 増加させます。大量のデータにとっては、これが重大なストレージや帯域幅のオーバーヘッドにつながる可能性があります。

2. パフォーマンスへの影響：エンコーディングとデコーディングのプロセスには CPU 時間が必要です。大量のデータや高頻度の操作において、これはパフォーマンスのボトルネックになることがあります。

3. セキュリティの誤解：多くの人が Base64 を一種の暗号化と誤解しています。実際には、Base64 は単なるエンコーディングであり、簡単にデコードできます。機密情報の保護には使用しないでください！

4. 読解性：Base64 でエンコードされたデータは人間にとっては判読できません。これがデバッグを難しくすることがあります。

大規模なアプリケーションで Base64 を使用する際には、次の最適化戦略を考慮してください：

- 必要なデータのみを Base64 エンコードする
- 特化した Base64 エンコーディング/デコーディングライブラリの使用を検討する。一般的なライブラリよりも効率的な場合が多いです
- サーバー負荷を軽減するためにクライアント側で Base64 エンコーディング/デコーディングを実行する

## 結論

Base64 は、正しいシナリオで使用すれば、多くの問題を解決できるシンプルかつ強力なツールです。その動作原理、適用シナリオ、および制限を理解することで、ソフトウェア開発におけるより賢明な判断ができるようになります。この記事が Base64 に関する総合的な理解を深め、関連する問題を楽に処理できるようになるための手助けとなれば幸いです。

すべての技術ツールと同様に、重要なのは Base64 を正しいタイミングで、そして適切な場所で使用することです。皆さんのプログラミングの旅に幸運を祈ります！

<LogtoCloudButton />