Base64エンコーディング解説:使用するタイミングと方法
· 12分で読めます
目次
Base64エンコーディングとは?
Base64は、バイナリデータをASCII文字列に変換するバイナリからテキストへのエンコーディング方式です。64個の印刷可能な文字のみを使用してバイナリデータを表現します:A-Z、a-z、0-9、+、/で、=はパディングに使用されます。
このエンコーディングにより、電子メール、JSON API、XMLドキュメント、HTMLなどのテキストのみのチャネルを通じてバイナリデータを安全に送信できます。Base64がなければ、バイナリデータはテキストを期待するシステムによって破損または誤解釈される可能性があります。
「Base64」という名前は、エンコーディングで使用される64文字のアルファベットに由来します。暗号化やハッシュ化とは異なり、Base64はセキュリティ対策ではありません。単にバイナリデータをテキストとして表現する方法です。誰でもキーやパスワードなしでBase64を元の形式にデコードできます。
Base64は現代のWeb開発のあらゆる場所に存在します:
- 画像を埋め込むためのHTMLとCSSのデータURI
- MIMEエンコーディングを使用した電子メールの添付ファイル
- 認証用のJWT(JSON Web Token)
- API認証ヘッダー(Basic認証)
- JSONまたはXMLへのバイナリデータの保存
- Webフォームでのファイルアップロードのエンコーディング
- 証明書とキーファイル(PEM形式)
Base64をいつどのように使用するかを理解することは、Web API、データ送信、またはファイル処理を扱う開発者にとって基本的なスキルです。
Base64の内部動作
エンコーディングプロセスは、入力の3バイト(24ビット)ごとに4つのBase64文字(各6ビット)に変換します。これがBase64を定義する核となる数学的関係です。
具体例を使ったステップバイステップのプロセスは次のとおりです:
# ステップ1:3バイトの入力を取得
入力テキスト: "Hi!"
バイナリ: 01001000 01101001 00100001
# ステップ2:6ビットグループに分割
010010 000110 100100 100001
# ステップ3:各6ビットグループをBase64アルファベットにマッピング
010010 → S (18)
000110 → G (6)
100100 → k (36)
100001 → h (33)
# 結果: "Hi!" → "SGkh"
Base64アルファベットは、各6ビット値(0-63)を特定の文字にマッピングします:
| 値の範囲 | 文字 | 説明 |
|---|---|---|
| 0-25 | A-Z | 大文字 |
| 26-51 | a-z | 小文字 |
| 52-61 | 0-9 | 数字 |
| 62 | + | プラス記号 |
| 63 | / | スラッシュ |
| - | = | パディング文字 |
パディングの理解
入力長が3で割り切れない場合、Base64は=文字でパディングを追加して、出力長を4で割り切れるようにします。これにより、適切なデコードが保証されます。
# パディングの例
"A" → "QQ==" (1バイト → 2文字 + ==)
"AB" → "QUI=" (2バイト → 3文字 + =)
"ABC" → "QUJD" (3バイト → 4文字、パディングなし)
パディングは、元の入力に何バイトあったかをデコーダーに伝えます。これがないと、デコーダーは最後のグループに1、2、または3バイトを期待すべきかわかりません。
プロのヒント: Base64は常にデータサイズを約33%増加させます。3バイトごとに4文字になるため、300KBの画像はBase64エンコード後に約400KBになります。
なぜ1文字あたり6ビットなのか?
1文字あたり6ビットという選択は意図的なものです。6ビットでは、2^6 = 64の異なる値を表現でき、これは64文字のアルファベットに完全にマッピングされます。
これはまた、3バイト(24ビット)が4つの6ビットチャンクに均等に分割され、最小限のオーバーヘッドで効率的なエンコーディング方式を作成することを意味します。
実践的なエンコードとデコード
ほとんどのプログラミング言語は、Base64エンコードとデコードのための組み込み関数または標準ライブラリを提供しています。人気のある言語での実用的な例を以下に示します:
JavaScript / Node.js
// ブラウザ(モダン)
const text = "Hello, World!";
const encoded = btoa(text);
console.log(encoded); // SGVsbG8sIFdvcmxkIQ==
const decoded = atob(encoded);
console.log(decoded); // Hello, World!
// Node.js
const buffer = Buffer.from("Hello, World!");
const encoded = buffer.toString('base64');
console.log(encoded); // SGVsbG8sIFdvcmxkIQ==
const decoded = Buffer.from(encoded, 'base64').toString();
console.log(decoded); // Hello, World!
Python
import base64
# エンコード
text = "Hello, World!"
encoded = base64.b64encode(text.encode())
print(encoded) # b'SGVsbG8sIFdvcmxkIQ=='
# デコード
decoded = base64.b64decode(encoded).decode()
print(decoded) # Hello, World!
Java
import java.util.Base64;
// エンコード
String text = "Hello, World!";
String encoded = Base64.getEncoder().encodeToString(text.getBytes());
System.out.println(encoded); // SGVsbG8sIFdvcmxkIQ==
// デコード
byte[] decoded = Base64.getDecoder().decode(encoded);
System.out.println(new String(decoded)); // Hello, World!
コマンドライン
# エンコード
echo -n "Hello, World!" | base64
# SGVsbG8sIFdvcmxkIQ==
# デコード
echo "SGVsbG8sIFdvcmxkIQ==" | base64 -d
# Hello, World!
# ファイルをエンコード
base64 image.png > image.txt
# ファイルをデコード
base64 -d image.txt > image.png
素早いエンコードとデコードのタスクには、コードを書かずにブラウザで直接Base64エンコーダーツールを使用できます。
クイックヒント: バイナリファイルをエンコードする際は、テキスト表現ではなく、常に生のバイトで作業してください。バイナリを最初にテキストに変換すると、データが破損します。
Base64の一般的な使用例
Base64エンコーディングは、データ送信と保存における特定の問題を解決します。Base64に遭遇したり、使用する必要がある最も一般的なシナリオは次のとおりです:
1. 埋め込み画像用のデータURI
データURIを使用すると、別のHTTPリクエストなしでHTMLまたはCSSに画像を直接埋め込むことができます。これは、小さなアイコン、ロゴ、またはインラインSVGに特に便利です。
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA..." alt="Red dot" />
/* CSS */
.icon {
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0i...);
}
利点には、HTTPリクエストの削減と可用性の保証(壊れた画像リンクがない)が含まれます。ただし、これによりHTML/CSSファイルサイズが増加し、画像の個別のブラウザキャッシュが妨げられます。
2. 電子メールの添付ファイル(MIME)
電子メールプロトコルは7ビットASCIIテキスト用に設計されました。Base64エンコーディングにより、PDF、画像、ドキュメントなどのバイナリ添付ファイルを電子メールシステムを通じて安全に送信できます。
MIME(多目的インターネットメール拡張)標準は、電子メールメッセージの添付ファイルをエンコードするためにBase64を使用します。これは電子メールクライアントとサーバーによって自動的に処理されます。
3. API認証
HTTP Basic認証は、認証情報をAuthorizationヘッダーでBase64としてエンコードします:
// ユーザー名: user、パスワード: pass
// 結合: user:pass
// Base64: dXNlcjpwYXNz
Authorization: Basic dXNlcjpwYXNz
覚えておいてください:Base64は暗号化ではありません。HTTP経由のBasic認証は安全ではありません。認証情報を送信する際は常にHTTPSを使用してください。
4. JSON Web Token(JWT)
JWTは、ヘッダーとペイロードセクションにBase64URLエンコーディング(URL安全なバリアント)を使用します:
// JWT構造: header.payload.signature
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
各セクションはBase64URLエンコードされたJSONであり、JWTをURLとHTTPヘッダーで読み取り可能かつ送信可能にします。
5. データベースへのバイナリデータの保存
一部のデータベースまたはデータ形式(JSONやXMLなど)は、バイナリデータをうまく処理できません。Base64エンコーディングにより、バイナリデータをテキストとして保存できます:
{
"user_id": 12345,
"profile_image": "iVBORw0KGgoAAAANSUhEUgAAAAUA...",
"document": "JVBERi0xLjQKJeLjz9MKMSAwIG9iago8..."
}
これは、NoSQLデータベース、構成ファイル、およびバイナリデータを含める必要があるAPIレスポンスで一般的です。
6. 証明書とキーファイル
PEM(Privacy Enhanced Mail)形式は、証明書、秘密鍵、公開鍵をエンコードするためにBase64を使用します:
-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKL0UG+mRKmzMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
...
-----END CERTIFICATE-----
これにより、証明書とキーが異なるシステム間で移植可能になり、コピー&ペーストが簡単になります。
APIとWeb開発におけるBase64
Web APIは、さまざまな目的でBase64を頻繁に使用します。これらのパターンを理解することで、サードパーティのAPIを効果的に操作し、独自のAPIを設計できます。
ファイルアップロードAPI
多くのAPIは、JSONペイロード内のBase64エンコードされた文字列としてファイルアップロードを受け入れます:
POST /api/upload
Content-Type: application/json
{
"filename": "document.pdf",
"content": "JVBERi0xLjQKJeLjz9MK...",
"encoding": "base64"
}
このアプローチは小さなファイルには適していますが、大きなアップロードには非効率的になります。1〜2MBを超えるファイルの場合は、代わりにmultipart/form-dataまたは直接バイナリアップロードの使用を検討してください。
Webhookペイロード
Webhookには、バイナリコンテンツがJSONシリアル化を生き残ることを保証するために、Base64エンコードされたデータが含まれることがよくあります:
{
"event": "document.signed",
"document_id": "doc_123",
"signed_pdf": "JVBERi0xLjQKJeLjz9MK...",
"timestamp": "2026-03-31T10:30:00Z"
}
GraphQLとBase64
GraphQLは、カーソルベースのページネーションと複雑なIDのエンコーディングにBase64を一般的に使用します:
query {
users(first: 10, after: "Y3Vyc29yOjEwMA==") {
edges {
cursor
node {
id # 多くの場合Base64エンコード: "VXNlcjoxMjM="
name
}
}
}
}
Relay仕様がこのパターンを普及させ、Base64を使用してカーソル位置とグローバルIDをエンコードしています。
プロのヒント: APIを設計する際は、標準のBase64またはBase64URLエンコーディングを使用しているかどうかを文書化してください。違いはURLパラメータにとって重要であり、微妙なバグを引き起こす可能性があります。
ブラウザAPIとBase64
最新のブラウザAPIは頻繁にBase64を使用します:
// CanvasからBase64へ
const canvas = document.getElementById('myCanvas');
const dataURL = canvas.toDataURL('image/png');
// data:image/png;base64,iVBORw0KGgo...
// ファイルからBase64へ
const file = document.getElementById('fileInput').files[0];
const reader = new FileReader();
reader.onload = (e) => {
const base64 = e.target.result.split(',')[1];
console.log(base64);
};
reader.readAsDataURL(file);
// Base64認証でFetch
fetch('/api/data', {
headers: {
'Authorization': 'Basic ' + btoa('username:password')
}
});
パフォーマンスの考慮事項とオーバーヘッド
Base64エンコーディングには、パフォーマンス、帯域幅、ストレージに影響するトレードオフがあります。これらを理解することで、いつ使用するかについて情報に基づいた決定を下すことができます。
サイズオーバーヘッド
Base64はデータサイズを約33%増加させます。計算は次のとおりです:
- 3バイトの入力 → 4バイトの出力
- オーバーヘッド: (4 - 3) / 3 = 33.33%
- 300KBの画像はエンコード時に約400KBになります
- 1MBのファイルはエンコード時に約1.33MBになります
| 元のサイズ | Base64サイズ | オーバーヘッド |
|---|---|---|
| 10 KB | 13.3 KB | +3.3 KB |
| 100 KB | 133 KB | +33 KB |
| 1 MB | 1.33 MB | +333 KB |
| 10 MB | 13.3 MB | +3.3 MB |
| 100 MB | 133 MB | +33 MB |
このオーバーヘッドは、帯域幅が制限された環境、モバイルアプリケーション、大きなファイル転送にとって重要です。
処理速度
Base64のエンコードとデコードにはCPUサイクルが必要です。少量のデータの場合、これは無視できます。大きなファイルまたは高スループットシステムの場合、ボトルネックになる可能性があります。
最新の実装は高度に最適化されていますが、パフォーマンスが重要な場合はベンチマークを取る必要があります:
// JavaScriptベンチマークの例
const data = new Uint8Array(1024 * 1024); // 1MB
crypto.getRandomValues(data);
console.time('encode');
const encoded = btoa(String.fromCharCode(...data));
console.timeEnd('encode');
console.time('decode');
const decoded = atob(encoded);
console.timeEnd('decode');
メモリ使用量
Base64操作は通常、元のデータとエンコードされたデータの両方を同時にメモリに保持する必要があります。大きなファイルの場合、これによりエンコード/デコード中のメモリ要件が2倍になる可能性があります。
大きなファイルにはストリーミングアプローチを検討してください:
// Node.jsストリーミングの例
const fs = require('fs');
const { Transform } = require('stream');
fs.createReadStream('large-file.bin')
.pipe(new Transform({
transform(chunk, encoding, callback) {
callback(null, chunk.toString('base64'));
}
}))
.pipe(fs.createWriteStream('large-file.b64'));