開発 · 5分で読めます ·

Base64とは?用途と、暗号化ではない理由

Base64はメール、data URI、APIのヘッダー、JWTに登場します。仕組み、データが3分の1大きくなる理由、そして何も隠さない理由を解説します。

Base64はソフトウェアのいたるところにあります。メールの添付ファイル、CSSに埋め込まれた画像、HTTP Basic認証のAuthorizationヘッダー、JWTの各部分。役目はただ一つ、バイナリを含むどんなデータも、安全なテキスト文字だけで書き表すことです。

仕組み

Base64はデータを3バイト(24ビット)ずつ取り出し、6ビットずつ4つのグループに分けます。各グループは0〜63の数で、A-Z、a-z、0-9、+、/ の64文字のどれかに対応します。入力が3バイトずつに割り切れないときは、末尾を = で埋めます。

テキスト  M        a        n
バイト    01001101 01100001 01101110
6ビット   010011 010110 000101 101110
Base64    T      W      F      u       →  TWFu

なぜ存在するのか

メールをはじめとする多くの古いシステムはテキスト向けに作られていて、任意のバイトを壊してしまうことがありました。Base64はどんなデータも普通の文字に変え、そうした経路をそのまま通れるようにします。代償はサイズで、3バイトが4文字になるため、エンコード後のデータは約33%大きくなります。

暗号化ではない

鍵はありません。Base64は誰でも一瞬でデコードできるので、何も隠せません。Basic認証ヘッダーのパスワード(dXNlcjpwYXNz は user:pass そのもの)は平文と同じくらい丸見えです。秘密はHTTPSと本物の暗号化で守り、Base64をセキュリティ対策と考えないでください。

よく見る派生形

Base64urlは + と / を - と _ に置き換え、たいてい埋め草を省くので、URLやファイル名で安全に使えます。JWTはこれを使っています。data URIは data:image/png;base64,iVBOR… のようにエンコードしたデータを直接埋め込みます。小さな画像ならリクエストを1回減らせますが、大きな画像では重くなります。

サイズを数字で見る

nバイトをエンコードした長さは4 × ceil(n / 3)文字なので、増加は約33%です。エンコーダーが改行を入れる場合は、さらにその分が加わります。

100KBの画像       →  Base64で約133KB
1MBの添付ファイル  →  約1.33MB(メールではさらに改行分)

デコードに失敗する理由

  • パディングの欠落:末尾の=を省くシステムがあり、厳格なデコーダーは入力を拒否します。長さが4の倍数になるまで=を足しましょう。
  • アルファベットの違い:Base64urlでは+と/の代わりに-と_を使います。Base64urlのデコーダーで戻すか、先に文字を置き換えましょう。
  • 改行と空白:メール(MIME)はBase64を76文字ごとに改行します。ほとんどのデコーダーは改行を無視しますが、すべてではありません。
  • 文字コードの取り違え:デコード結果はバイト列です。UTF-8の文章をLatin-1として読むと、日本語やヘブライ語、アクセント付き文字が文字化けします。

JavaScriptのbtoaの落とし穴

ブラウザ組み込みのbtoa()はLatin-1の文字しか受け付けず、日本語、中国語、絵文字などではエラーになります。まずTextEncoderなどで文字列をUTF-8のバイト列にしてから、Base64にエンコードしましょう。

使うべきとき、使うべきでないとき

Base64が適しているのは、バイナリデータをテキスト用の経路に通すときです。JSONやXMLのペイロード、メール、データURI、HTTPヘッダーなどがそうです。データを隠す、小さくする(必ず大きくなります)、大きなファイルをデータベースに保存するといった用途には向きません。データベースならバイナリ列やオブジェクトストレージのほうが小さく高速です。受け取る側が生のバイトを受け付けるなら、生のバイトを送りましょう。

試してみる

4DevのBase64エンコーダーは、入力したそばからテキストをBase64に変換します。UTF-8を使うので、日本語や絵文字など英語以外のテキストも正しくエンコードされます。逆方向にはBase64デコーダーを使ってください。

Base64エンコーダーを開く

LinkedInXFacebook