Base64エンコーディングとは?
Base64は、バイナリデータをASCII文字列形式で表現するバイナリ・トゥ・テキスト符号化方式です。特に、テキストデータを扱うように設計されたメディアを介してデータを転送する際に、バイナリデータをエンコードする必要がある場合によく使用されます。aGVsbG8gd29ybGQ= のような文字列を見て「これは何だろう」と思ったことがあるなら、それはBase64エンコーディングです。このガイドでは、Base64とは何か、その内部動作、存在理由、そして使用すべきタイミングについて説明します。
Base64が存在する根本的な理由は、多くのトランスポートプロトコルやデータ形式がテキスト用に設計されており、バイナリデータ用ではないからです。電子メールはもともと7ビットのASCIIテキストのみを扱うように設計されていました。JSONやXMLはテキストベースの形式です。URLには制限された文字セットがあります。画像ファイル、暗号鍵、その他のバイナリデータをこれらのチャネルを通じて送信する必要がある場合、バイトを安全なテキスト文字として表現する方法が必要です。Base64は、任意のバイトを64の安全な文字セットにマッピングすることでこの問題を解決します。
Base64が解決する問題
友達に写真をメールで送りたいと想像してください。写真はバイナリファイルとして保存されています。メールに添付する際、メールクライアントとサーバーはバイナリデータをエンコードして、テキストメッセージ用に設計されたメールインフラを安全に通過できるようにする必要があります。初期のメールシステムは、特定のバイト値を制御文字として解釈したり、各バイトから上位ビットを取り除いたりするため、バイナリデータを破損する可能性がありました。
Base64は、テキストベースのシステムで普遍的にサポートされている文字(大文字、小文字、数字、および2つの追加文字(+ と /)、さらにパディング文字(=))のみを使用してバイナリデータを表現することで、この問題を解決します。これにより、エンコードされたデータはASCIIテキストを扱うあらゆるシステムを通過しても安全に伝送されます。
Base64の仕組み
Base64は、3バイト(24ビット)のグループを4つの6ビットグループに変換します。各6ビットグループは、Base64アルファベットの文字にマッピングされます。この処理は決定論的かつ完全に可逆であり、Base64でエンコードされた文字列は元のバイナリデータにデコードできます。
ステップバイステップの処理
テキスト「Man」をエンコードする過程を追って、仕組みを理解しましょう。
-
各文字のASCII値を取得:
- M = 77(10進数)= 01001101(2進数)
- a = 97(10進数)= 01100001(2進数)
- n = 110(10進数)= 01101110(2進数)
-
8ビットの値を連結して24ビットのシーケンスに:
- 01001101 01100001 01101110
-
24ビットのシーケンスを4つの6ビットグループに分割:
- 010011 = 19
- 010110 = 22
- 000101 = 5
- 101110 = 46
-
各6ビット値をインデックステーブルを使用してBase64アルファベット文字にマッピング:
- 19 → T
- 22 → W
- 5 → F
- 46 → u
-
結果:「TWFu」
パディングの扱い
入力長が3バイトの倍数でない場合はどうなるでしょうか?Base64はパディングを使用してこのケースを処理します。最後のグループが1バイト(8ビット)のみの場合、4つのゼロビットでパディングされて2つの6ビットグループを形成し、2つのパディング文字(==)が追加されます。最後のグループが2バイト(16ビット)の場合、2つのゼロビットでパディングされて3つの6ビットグループを形成し、1つのパディング文字(=)が追加されます。
例えば、1バイトの「M」(01001101)をエンコードする場合:
- 24ビットグループ:01001101 00000000 00000000(ゼロでパディング)
- 6ビットグループ:010011 = 19 → T、010000 = 16 → Q、000000 = 0 → A、000000 = 0 → A
- ただし、1バイトしか提供されていないため、
==パディングを追加 - 結果:「TQ==」
パディングにより、エンコードされた出力長が常に4文字の倍数になります。デコーダーはパディングを使用して、バイナリに戻す際に破棄するバイト数を判断します。
Base64アルファベット完全表
| 値 | 文字 | 値 | 文字 | 値 | 文字 | 値 | 文字 |
|---|---|---|---|---|---|---|---|
| 0 | A | 16 | Q | 32 | g | 48 | w |
| 1 | B | 17 | R | 33 | h | 49 | x |
| 2 | C | 18 | S | 34 | i | 50 | y |
| 3 | D | 19 | T | 35 | j | 51 | z |
| 4 | E | 20 | U | 36 | k | 52 | 0 |
| 5 | F | 21 | V | 37 | l | 53 | 1 |
| 6 | G | 22 | W | 38 | m | 54 | 2 |
| 7 | H | 23 | X | 39 | n | 55 | 3 |
| 8 | I | 24 | Y | 40 | o | 56 | 4 |
| 9 | J | 25 | Z | 41 | p | 57 | 5 |
| 10 | K | 26 | a | 42 | q | 58 | 6 |
| 11 | L | 27 | b | 43 | r | 59 | 7 |
| 12 | M | 28 | c | 44 | s | 60 | 8 |
| 13 | N | 29 | d | 45 | t | 61 | 9 |
| 14 | O | 30 | e | 46 | u | 62 | + |
| 15 | P | 31 | f | 47 | v | 63 | / |
パディング文字 = は、入力データ長が3バイトの倍数でない場合に使用されます。
一般的なユースケース
Base64エンコーディングは、Web開発やソフトウェア工学のさまざまなコンテキストで登場します。
| ユースケース | 説明 |
|---|---|
| Data URI | HTMLやCSSへの画像埋め込み |
| HTTP基本認証 | ヘッダー内の認証情報のエンコード |
| JSON/XMLペイロード | テキスト形式でのバイナリデータ保存 |
| メール添付ファイル | MIME Base64エンコーディング |
| JWTトークン | ヘッダーとペイロードのエンコード |
Data URI
Data URIを使用すると、画像、フォント、その他のリソースをHTMLやCSSファイルに直接埋め込めます。外部の画像ファイルにリンクする代わりに、画像をBase64でエンコードしてインラインで含めます:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...">
これによりHTTPリクエストが不要になりますが、サイズが33%増加します。Data URIは、アイコン、ロゴ、UI要素などの小さなアセットに最も適しています。
HTTP基本認証
HTTP基本認証は、認証情報をBase64でエンコードした文字列として Authorization ヘッダーで送信します。形式は Basic base64(ユーザー名:パスワード) です。Base64は暗号化ではないことに注意してください。認証情報はリクエストを傍受した人なら誰でも簡単にデコードできます。基本認証は常にHTTPS上で使用し、転送中の認証情報を保護する必要があります。
Authorization: Basic am9objpzZWNyZXQ=
am9objpzZWNyZXQ= をデコードすると john:secret が明らかになります。
JSONおよびXMLペイロード
JSONやXMLのペイロードにバイナリデータ(ファイルアップロード、暗号鍵、画像サムネイルなど)を含める必要がある場合、Base64が標準的なアプローチです。バイナリデータはBase64文字列に変換され、プロパティ値として含められます:
{
"filename": "photo.jpg",
"data": "/9j/4AAQSkZJRgABAQAAAQABAAD//gA..."
}
メール添付ファイル(MIME)
MIME(Multipurpose Internet Mail Extensions)標準は、メール添付ファイルのエンコードにBase64を使用します。画像を添付したメールを送信すると、メールクライアントが画像をBase64に変換し、適切なMIMEヘッダーでラップしてメール本文に含めます。受信側のメールクライアントはBase64を元の画像ファイルにデコードします。
JWTトークン
JSON Web Token(JWT)は、Base64URLと呼ばれるURLセーフなBase64派生形式を使用してヘッダーとペイロードをエンコードします。Base64URLは + を - に、/ を _ に置き換え、= パディングを削除します。結果はコンパクトでURLセーフなトークンとなり、認証と認可の情報を運びます。
コードでのエンコードとデコード
ほとんどのプログラミング言語は、Base64エンコードとデコードのための組み込み関数を提供しています。
JavaScript(ブラウザ)
// エンコード
const encoded = btoa('Hello, World!');
console.log(encoded); // "SGVsbG8sIFdvcmxkIQ=="
// デコード
const decoded = atob(encoded);
console.log(decoded); // "Hello, World!"
Node.js
const encoded = Buffer.from('Hello, World!').toString('base64');
console.log(encoded); // "SGVsbG8sIFdvcmxkIQ=="
const decoded = Buffer.from(encoded, 'base64').toString('utf-8');
console.log(decoded); // "Hello, World!"
Python
import base64
encoded = base64.b64encode(b'Hello, World!')
print(encoded) # b'SGVsbG8sIFdvcmxkIQ=='
decoded = base64.b64decode(encoded)
print(decoded) # b'Hello, World!'
PHP
$encoded = base64_encode('Hello, World!');
echo $encoded; // "SGVsbG8sIFdvcmxkIQ=="
$decoded = base64_decode($encoded);
echo $decoded; // "Hello, World!"
サイズのオーバーヘッド
Base64エンコーディングは、データサイズを約33%増加させます。入力の3バイトごとに、Base64は4バイトの出力を生成します。このオーバーヘッドは、テキストベースのシステムでバイナリデータを安全に扱うための代償です。
実用的には、1MBのバイナリファイルはBase64エンコード後、約1.37MBになります。大量のデータをBase64エンコードする前に、エンコードのオーバーヘッドがユースケースに許容できるか検討してください。少量のデータ(アイコン、トークン、短いメッセージ)ではオーバーヘッドは無視できます。大量のファイル(写真、動画、アーカイブ)ではオーバーヘッドが大きくなる可能性があるため、代替アプローチを検討する必要があります。
Base64の派生形式
上記で説明した標準のBase64アルファベットだけが唯一の派生形式ではありません。異なるアプリケーションは、特定の制約に合わせてわずかに異なるアルファベットを使用します。
Base64URL は + を - に、/ を _ に置き換え、パディングを省略します。この派生形式は、追加のエンコードなしでURLやファイル名で安全に使用できます。JWT、OAuthトークン、Web暗号APIで使用されています。
MIME Base64 はメールで使用される派生形式で、メールの行長制限に準拠するため76文字ごとに改行が入ります。
PEM(Privacy-Enhanced Mail)は、X.509証明書、秘密鍵、その他の暗号オブジェクトをエンコードするために、ヘッダーとフッターの行(-----BEGIN CERTIFICATE-----)とともにBase64エンコーディングを使用します。
なぜ暗号化ではないのか?
Base64は暗号化ではありません。これは符号化方式であり、鍵がなくても簡単にデコードできます。アルゴリズムは公開されており、アルファベットは固定されており、開発者なら誰でも組み込み関数を使って数分でBase64文字列をデコードできます。
機密データを保護するためにBase64を使用してはなりません。Base64は機密性、完全性、認証のいずれも提供しません。不正アクセスからデータを保護する必要がある場合は、AES(対称)やRSA(非対称)のような適切な暗号化アルゴリズムを使用してください。データが改ざんされていないことを確認する必要がある場合は、SHA256などの暗号学的ハッシュ関数をデジタル署名やHMACと組み合わせて使用してください。
初心者がよく犯す間違いは、出力がランダムな文字に見えるため、Base64を暗号化の一種だと思うことです。実際には、Base64は簡単に元に戻せ、何のセキュリティも提供しません。セキュリティ目的には常に確立された暗号アルゴリズムを使用し、Base64は本来の目的であるテキストベースの転送のためのバイナリデータの安全なエンコードにのみ使用してください。