Base64エンコードとは?仕組みと使いどころ
Base64エンコードとは
Base64は、バイナリデータをASCII文字列に変換するエンコード方式です。名前の通り、64種類の印刷可能な文字(A-Z、a-z、0-9、+、/)とパディング文字(=)を使って、あらゆるバイナリデータをテキスト形式で表現します。
「エンコード」と聞くと暗号化を連想するかもしれませんが、Base64は暗号化ではありません。誰でも簡単にデコード(復元)できる、単なるデータの表現方法の変換です。
エンコードの仕組み
Base64のエンコードプロセスを段階的に見ていきましょう。
変換の流れ
- 入力データをバイト列(8ビット単位)として扱う
- バイト列を6ビット単位に分割する
- 各6ビットの値を変換テーブルで対応する文字に置き換える
- 出力が4の倍数になるようパディング(
=)を追加する
変換テーブル
6ビットで表現できる値は0〜63の64通りです。それぞれに以下の文字が対応します。
| 値の範囲 | 対応文字 | 文字数 |
|---|---|---|
| 0〜25 | A〜Z | 26 |
| 26〜51 | a〜z | 26 |
| 52〜61 | 0〜9 | 10 |
| 62 | + | 1 |
| 63 | / | 1 |
合計64文字に、パディング用の = を加えた65種類の文字で構成されます。
具体例: 「ABC」のエンコード
「ABC」という文字列をBase64にエンコードする過程を追ってみましょう。
ステップ1: ASCIIコードへの変換
A = 65 = 01000001
B = 66 = 01000010
C = 67 = 01000011
ステップ2: 8ビット列を連結し、6ビット単位に分割
8ビット列: 01000001 01000010 01000011
6ビット列: 010000 | 010100 | 001001 | 000011
ステップ3: 変換テーブルで文字に置換
010000 = 16 → Q
010100 = 20 → U
001001 = 9 → J
000011 = 3 → D
結果: ABC → QUJD
パディングの仕組み
入力データのバイト数が3の倍数でない場合、6ビット分割で余りが生じます。この場合、足りないビットを0で埋め、出力が4文字の倍数になるよう = を追加します。
| 入力バイト数 | パディング | 例 |
|---|---|---|
| 3の倍数 | なし | ABC → QUJD |
| 余り1バイト | == |
A → QQ== |
| 余り2バイト | = |
AB → QUI= |
データサイズの増加
Base64エンコードでは、3バイトの入力が4文字の出力になります。つまり、元のデータに対して約33%(正確には4/3倍)サイズが増加します。
元データ: 3 バイト → Base64: 4 文字(4バイト)
増加率: (4 - 3) / 3 = 約33%
この点は、Base64を使用する際に常に考慮すべきトレードオフです。
主な使用場面
メール添付ファイル(MIME)
電子メールの通信プロトコル(SMTP)は、もともと7ビットASCIIテキストしか扱えない設計でした。画像やPDFなどのバイナリファイルをメールに添付するために、MIME(Multipurpose Internet Mail Extensions)規格でBase64エンコードが採用されています。
Content-Type: image/png
Content-Transfer-Encoding: base64
iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJ
AAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5E
rkJggg==
Data URI(データURL)
HTMLやCSSに画像を直接埋め込む際にBase64が使われます。小さなアイコンやインライン画像をHTTPリクエストなしで表示できるため、リクエスト数の削減に有効です。
<!-- 小さなアイコンをData URIで埋め込み -->
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUh..." alt="アイコン">
/* CSSでの背景画像埋め込み */
.icon {
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0i...");
}
ただし、Data URIにはいくつかの注意点があります。
- Base64化によりデータサイズが約33%増加する
- ブラウザのキャッシュが効かない(HTMLファイルと一体化するため)
- 大きな画像には不向き(目安として数KB以下の画像に限定すべき)
JWT(JSON Web Token)
認証トークンとして広く使われるJWTは、Base64URLエンコード(後述)を使用しています。JWTは3つのパートをドット(.)で連結した構造です。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IlRhbmFrYSJ9.
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
各パートの内容は以下の通りです。
| パート | 内容 | デコード結果の例 |
|---|---|---|
| ヘッダー | アルゴリズム情報 | {"alg": "HS256", "typ": "JWT"} |
| ペイロード | ユーザー情報等 | {"sub": "1234567890", "name": "Tanaka"} |
| 署名 | 改ざん検知用 | (バイナリデータ) |
APIレスポンスでのバイナリデータ
JSON形式のAPIレスポンスにバイナリデータ(画像、ファイルなど)を含める場合にも、Base64エンコードが活用されます。
{
"fileName": "report.pdf",
"mimeType": "application/pdf",
"content": "JVBERi0xLjQKMSAwIG9iago8PA..."
}
Base64の派生形式
標準のBase64以外にも、用途に応じた派生形式があります。
Base64URL
URLやファイル名で使用できるよう、標準Base64の + を - に、/ を _ に置き換えた形式です。JWTやURLパラメータで使われます。パディングの = も省略されることがあります。
| 標準Base64 | Base64URL |
|---|---|
+ |
- |
/ |
_ |
=(パディング) |
省略可 |
MIME Base64
メール送信用に、76文字ごとに改行(CRLF)を挿入する形式です。
メリットとデメリット
メリット
- テキストベースのプロトコルでバイナリデータを安全に転送できる
- ASCII文字のみで構成されるため、文字化けのリスクがない
- JSONやXMLなどのテキストフォーマットにバイナリデータを埋め込める
- エンコード・デコードが高速で、実装も容易
デメリット
- データサイズが約33%増加する
- エンコード・デコードの処理コストが(わずかながら)発生する
- 大量のバイナリデータの転送には非効率
- 可読性がない(人間が見て内容を判断できない)
セキュリティ上の注意点
Base64に関して、よくある誤解とセキュリティ上の注意点を整理します。
Base64は暗号化ではない
最も重要な点として、Base64は暗号化ではありません。エンコードされたデータは誰でもデコードできます。パスワードやAPIキーなどの機密情報をBase64でエンコードしただけでは、セキュリティ対策にはなりません。
// これはセキュリティ対策にならない
const encoded = btoa("my-secret-password");
// "bXktc2VjcmV0LXBhc3N3b3Jk" → 誰でもデコード可能
機密情報を保護するには、AESなどの適切な暗号化アルゴリズムを使用してください。
JWTのペイロードは読み取り可能
JWTのペイロード部分はBase64URLでエンコードされているだけで、暗号化されていません。つまり、トークンを取得した人は誰でもペイロードの内容を読めます。JWTの署名は改ざん検知のためのものであり、内容の秘匿化のためではありません。
機密性の高いデータをJWTに含める必要がある場合は、JWE(JSON Web Encryption)を使用してペイロードを暗号化します。
入力の検証
外部から受け取ったBase64データをデコードする際は、入力の検証を忘れないでください。不正なBase64文字列や、デコード後に予期しないデータが含まれている可能性があります。
function safeBase64Decode(input) {
// Base64文字列の形式チェック
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(input)) {
throw new Error("Invalid Base64 string");
}
return atob(input);
}
プログラミング言語での実装
主要な言語でのBase64エンコード・デコードの方法を示します。
JavaScript(ブラウザ / Node.js)
// ブラウザ環境
const encoded = btoa("Hello, World!"); // エンコード
const decoded = atob("SGVsbG8sIFdvcmxkIQ=="); // デコード
// Node.js 環境
const buf = Buffer.from("Hello, World!");
const encoded = buf.toString("base64");
const decoded = Buffer.from(encoded, "base64").toString("utf-8");
Python
import base64
encoded = base64.b64encode(b"Hello, World!").decode("utf-8")
decoded = base64.b64decode(encoded).decode("utf-8")
まとめ
Base64はバイナリデータをテキスト形式に変換するシンプルかつ実用的なエンコード方式です。メールの添付ファイル、Data URI、JWT、APIレスポンスなど、Web開発の多くの場面で活用されています。約33%のサイズ増加というトレードオフを理解した上で、適切な場面で使い分けることが重要です。そして最も大切な点として、Base64は暗号化ではないことを常に意識してください。
