Base64とは?
Base64は、バイナリデータを印刷可能なASCII文字のシーケンスとして表現するエンコード方式です。画像、PDF、生のバイナリデータなど、あらゆるバイト列を、64種類の安全な文字だけで構成された文字列にエンコードします。その文字とは:A–Z、a–z、0–9、+、/(パディングには=を使用)です。
「Base64」という名前は、このエンコードが64進数を使用しているという事実に由来しています。
64文字の内訳
| グループ | 文字 |
|---|---|
| 大文字 | A–Z(26文字) |
| 小文字 | a–z(26文字) |
| 数字 | 0–9(10文字) |
| 記号 | +、/(2文字) |
| パディング | = |
URLとの競合を避けるため、+を-に、/を_に置き換えたURLセーフ変体も存在します。
Base64エンコードの仕組み
Base64は、3バイトのバイナリデータを4つのBase64文字に変換することで機能します。
- 入力から3バイト(24ビット)を取得
- 4つの6ビットグループに分割
- 各6ビット値をBase64アルファベットの文字にマッピング
例:"Man"という文字列のエンコード
| 文字 | M | a | n |
|---|---|---|---|
| ASCII | 77 | 97 | 110 |
| バイナリ | 01001101 | 01100001 | 01101110 |
結合:010011010110000101101110
6ビットグループに分割:010011 | 010110 | 000101 | 101110
マッピング:T | W | F | u → "TWFu"
入力が3バイトの倍数でない場合、最後のグループを完成させるために=文字でパディングされます。
データサイズのオーバーヘッド
Base64エンコードによりデータサイズが約33%増加します(3バイトごとに4文字になる)。大きなデータにBase64を使用するかどうか判断する際は、この点を考慮してください。
簡単な歴史
Base64は、MIME(多目的インターネットメール拡張)の文脈で開発され、1992年にRFC 1341で標準化されました。メールシステムはもともと7ビットASCIIテキストしか送信できない設計でしたが、画像やドキュメントなどの添付ファイルはバイナリデータです。Base64は、バイナリデータをプレーンテキストとしてエンコードすることで、メールインフラを安全に通過できるようにしてこの問題を解決しました。
名前とコンセプトは、Unixのuuencode(異なるが関連するスキーム)にさらに早く登場していましたが、MIMEのBase64が永続的な標準となりました。
よくある使用場面
1. HTML/CSSへの画像の埋め込み
外部画像ファイルを参照する代わりに、Base64エンコードされたデータURIを使って画像を直接埋め込むことができます:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..." />
使うべき場面:クリティカルレンダリングパスでHTTPリクエストを節約できる小さなアイコンや画像。
避けるべき場面:大きな画像——33%のサイズオーバーヘッドと画像を個別にキャッシュできないことで、メリットよりデメリットが大きくなります。
2. HTTP基本認証
HTTP Basic認証では、Authorizationヘッダー内にBase64エンコードされた文字列として認証情報が送信されます:
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
これはusername:passwordをBase64エンコードしたものです。重要:これは暗号化ではありません——簡単にデコードできます。Basic認証を使う場合は必ずHTTPSを使用してください。
3. JWT(JSON Web Token)
JWTトークンは、ドットで区切られた3つのBase64URLエンコードされたセクション(ヘッダー、ペイロード、署名)で構成されています。ヘッダーとペイロードは読み取り可能です(暗号化されていません)——ここでのBase64は純粋にトランスポートエンコードのためです。
4. メール添付ファイル(MIME)
Base64の元々のユースケースとして:メールクライアントはバイナリ添付ファイル(画像、PDFなど)をBase64でエンコードし、メールインフラを通じて安全に送信します。
5. JSONやXMLへのバイナリデータの格納
JSONとXMLはテキストのみをサポートするため、バイナリデータ(暗号化キーや小さな画像など)は含める前にBase64エンコードされることが多いです。
6. CSSでのデータURL
CSSに背景画像をインライン化できます:
background-image: url('data:image/svg+xml;base64,PHN2ZyB4...');
Base64の変体
| 変体 | 文字 | 使用場面 |
|---|---|---|
| 標準Base64 | A–Z a–z 0–9 + / | 汎用 |
| URLセーフBase64 | A–Z a–z 0–9 - _ | URL、ファイル名、JWT |
| パディングなしBase64 | =を省略 | 一部のAPIで推奨 |
| MIME Base64 | 標準+76文字ごとに改行 | メール |
セキュリティに関する考慮事項
Base64は暗号化ではない
これが最も重要な点です:Base64はエンコードであり、暗号化ではありません。Base64文字列を持っている人なら誰でも即座にデコードできます——鍵は不要です。機密情報を「隠す」ためにBase64を使用しないでください。
echo "dXNlcm5hbWU6cGFzc3dvcmQ=" | base64 --decode
# 出力: username:password
パスワードをBase64でエンコードしない
パスワードをBase64で保存してもセキュリティはゼロです。代わりに、bcrypt、Argon2、scryptなどの適切なパスワードハッシュアルゴリズムを使用してください。
データURIとXSSリスク
Base64データURI自体は安全ですが、一部のブラウザコンテキストでは、data:text/html;base64,...というURIを通じて悪意のあるJavaScriptをエンコードして実行できる場合があります。最新のブラウザのほとんどはリンクナビゲーションやiframeソースに対してこれを制限していますが、ユーザーが提供するデータURIは常にサニタイズしてください。
プログラミング言語でのBase64
JavaScript
// エンコード
const encoded = btoa("Hello, World!"); // "SGVsbG8sIFdvcmxkIQ=="
// デコード
const decoded = atob("SGVsbG8sIFdvcmxkIQ=="); // "Hello, World!"
注意:btoa/atobはブラウザではLatin-1文字列でのみ動作します。Unicodeの場合:
// Unicodeセーフエンコード
const encoded = btoa(unescape(encodeURIComponent("こんにちは")));
またはNode.jsでBufferを使用:
Buffer.from("Hello").toString("base64");
Buffer.from("SGVsbG8=", "base64").toString("utf8");
Python
import base64
# エンコード
encoded = base64.b64encode(b"Hello, World!").decode("utf-8")
# "SGVsbG8sIFdvcmxkIQ=="
# デコード
decoded = base64.b64decode("SGVsbG8sIFdvcmxkIQ==").decode("utf-8")
# "Hello, World!"
# URLセーフ変体
url_safe = base64.urlsafe_b64encode(b"Hello+World/")
パフォーマンスに関する考慮事項
- エンコード/デコードは高速:ほとんどのユースケースでBase64のオーバーヘッドは無視できます。
- サイズオーバーヘッド:バイナリより約33%大きくなります。頻繁に転送する大きなファイル(MB以上)には避けてください。
- CPUキャッシュへの負荷:メモリ内で大きなバイナリファイルをエンコードすると、CPUキャッシュに負荷がかかる可能性があります。
大きなバイナリ転送には、Base64よりもバイナリプロトコル(バイナリフレームのHTTP/2、WebSocketバイナリフレーム、protobufを使ったgRPC)を優先してください。
まとめ
Base64は、ほとんどの開発者が意識せずに使っている、現代のWebの基盤となる技術の一つです。テキストベースのシステムでの送信のために、バイナリデータを印刷可能なテキストとして安全にエンコードするという特定の問題をうまく解決します。
Base64を使うべき場面:テキストコンテキスト(HTML、JSON、メール、ヘッダー)にバイナリデータを埋め込む必要がある場合。
Base64を使うべきでない場面:データを暗号化したり保護したりしたい場合——Base64は鍵なしで完全に元に戻すことができます。