Base64エンコーダーをJavaScriptで作った話|「なぜ64文字なのか」から始める仕組み解説

Base64エンコーダーをJavaScriptで作った話|「なぜ64文字なのか」から始める仕組み解説

「JWTって eyJ で始まる謎の文字列だよね」「PEMファイルの中身を見たら英数字がずらっと並んでた」

エンジニアを目指していると、こういう場面に出くわします。あの文字列の正体が Base64(ベースロクヨン) です。

この記事は、Lapis Tech Toolsで公開している Base64 エンコーダー・デコーダー を題材に、Base64が生まれた理由・仕組み・JavaScriptでの実装方法を、プログラミング未経験者にもわかるように解説します。

前回のIPアドレス計算機の解説記事と同じく「なぜこうしたのか?」を軸に読み進めてください。


1. Base64が生まれた理由:「文字化け」問題

インターネットの黎明期、メールの仕組み(SMTPというプロトコル)は英数字しか扱えませんでした

日本語・絵文字・画像・PDFといったデータを送ろうとすると、受け取った側で文字化けしたり、データが壊れたりする問題が起きました。

なぜ英数字しか扱えなかったのか?

コンピューターは最終的にすべての情報を「0と1のビット列」で扱います。古い通信規格では「7ビットまでの文字(128種類)」しかやり取りできないものが多く、それを超えるデータは送受信の途中で壊れてしまうことがありました。

そこで考えられた解決策が「どんなデータでも、絶対に安全な文字だけで表現できないか?」という発想です。これがBase64です。


2. なぜ「64」なのか

Base64が使う文字はちょうど64種類です:

  • 大文字 A〜Z(26文字)
  • 小文字 a〜z(26文字)
  • 数字 0〜9(10文字)
  • 記号 +/(2文字)

合計64文字。

なぜ64文字なのか?

64は 2の6乗 です。コンピューターは0と1しか扱えないので、「6ビットで表現できる数(0〜63)」と64種類の文字を1対1で対応させると都合が良いのです。任意のデータを「6ビットずつ切り出して→対応する文字に変換」という操作でBase64文字列が作れます。


3. 手を動かして理解する:「A」をBase64に変換してみよう

「A」という文字をBase64に変換する過程を手順で追ってみます。

Step 1:「A」をASCIIコード(10進数)に変換

「A」のASCIIコードは 65 です。

Step 2:2進数(8ビット)に変換

65 を2進数にすると 01000001 です。

Step 3:6ビットずつ区切る

1文字(8ビット)を6ビット単位に分けるには、文字が3つ必要です(3文字 = 24ビット = 6ビット×4グループ)。 「A」だけでは6ビット×4グループに満たないため、末尾に0を足してパディングします:

01000001 → 010000 010000(6ビット×2グループ)
                + 000000 000000(パディングの0を足す)

Step 4:各グループを対応する文字に変換

6ビット値10進数Base64文字
01000016Q
01000016Q
(パディング)=
(パディング)=

結果:AQQ==

実際にツールで「A」を入力すると QQ== と表示されます。= はパディング(端数の補完)の印です。


4. JavaScriptの実装:btoaatob

JavaScriptには最初からBase64変換の関数が組み込まれています:

// エンコード(テキスト → Base64)
btoa("Hello World")  // → "SGVsbG8gV29ybGQ="

// デコード(Base64 → テキスト)
atob("SGVsbG8gV29ybGQ=")  // → "Hello World"

btoaatob の名前の由来は?

btoa は “binary to ASCII”、atob は “ASCII to binary” の略です。 「base64」という単語は入っていませんが、歴史的にBase64がASCIIへの変換方法として使われてきたため、この名前になっています。

シンプルで便利ですが、日本語を入力するとエラーになります。

btoa("こんにちは")  // → エラー!

なぜ日本語ではエラーになるのか?

btoa は「1文字 = 1バイト」という前提で動きます。しかし日本語などの文字は「1文字 = 3バイト(UTF-8エンコード)」で表現されます。この不一致でエラーが起きます。


5. 日本語対応の実装:UTF-8処理を追加する

このツールでは日本語も扱えるよう、以下の処理を追加しています:

// UTF-8対応のエンコード
function utf8_to_b64(str) {
  return window.btoa(
    encodeURIComponent(str).replace(
      /%([0-9A-F]{2})/g,
      function(match, p1) {
        return String.fromCharCode(Number('0x' + p1));
      }
    )
  );
}

// UTF-8対応のデコード
function b64_to_utf8(str) {
  return decodeURIComponent(
    window.atob(str)
      .split('')
      .map(function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
      })
      .join('')
  );
}

複雑に見えますが、やっていることはシンプルです:

  1. encodeURIComponent("こんにちは")%E3%81%93%E3%82%93...(URLエンコード)
  2. %E3\xE3 のようにバイト列に変換
  3. それを btoa に渡す

なぜこの回り道が必要なのか?

encodeURIComponent はJavaScriptに元から組み込まれた「URLで使えない文字をパーセント記法に変換する」関数です。日本語を一度URLエンコードしてからバイト列に変換することで、btoa が扱える「1バイトずつのデータ」に変換できます。


6. 入力バリデーション:不正なBase64を弾く

デコード時、入力が正しいBase64文字列でなければエラーを表示する処理も入れています:

// Base64として有効な文字だけで構成されているかチェック
if (!/^[A-Za-z0-9+/=]*$/.test(val.replace(/\s/g, ''))) {
  throw new Error("無効なBase64文字列です。");
}

なぜこのチェックが必要なのか?

Base64では A-Z, a-z, 0-9, +, /, = 以外の文字は使いません。日本語や記号(! など)が混ざっていたらBase64ではないのでデコードする前に弾いた方が、ユーザーに早く分かりやすいエラーを返せます。エラーが起きてから「失敗しました」と表示するより、原因を伝える方がUXが良いです。


7. UIで気をつけたこと

ツールのUIは「左がテキスト、右がBase64」という2カラム構成です。

[ 通常テキスト   ]  →エンコード→  [ Base64データ  ]
[ こんにちは    ]  ←デコード←   [ 44GT44KT44Gr... ]

なぜ横並びにしたのか?

Base64の操作は「変換前 ↔ 変換後」を行き来します。横並びにすることで、両方を同時に目で確認しながら操作できます。変換結果を確認してからコピーするまでの手の動きも最短になります。テキストエリアを2段に縦積みにした場合、変換前と変換後を同時に見るにはスクロールが必要になり不便です。


8. Base64は「暗号化」ではない

重要な注意点をひとつ。

btoa("password123")  // → "cGFzc3dvcmQxMjM="
atob("cGFzc3dvcmQxMjM=")  // → "password123"

誰でも一瞬で元に戻せます。Base64は「隠す」技術ではなく「安全な文字で表現する」技術です。

パスワードの保存にBase64を使ってはいけません。

パスワード保存には bcryptargon2 のようなハッシュ化アルゴリズムを使います。ハッシュ化は一方通行(元に戻せない)ため、データが漏洩しても元のパスワードが分かりません。Lapis Tech Toolsにはbcryptハッシュ生成ツールもあるので、ハッシュ化の動作を実際に試してみてください。

なぜエンジニアがこれを間違えるのか?

Base64でエンコードすると文字列が人間には読めなくなるため、「隠せている」と錯覚しやすいです。しかしデコードは誰でもできます。セキュリティの基礎として「エンコード ≠ 暗号化」は必ず覚えてください。


9. まとめ:一つのツールから学べること

Base64エンコーダーというシンプルなツールの裏側を見てきました。

  • コンピューターの基礎: ビット・バイト・2進数
  • 文字コードの知識: ASCII・UTF-8・エンコードの違い
  • JavaScript: btoa/atob・正規表現・エラーハンドリング
  • UI設計: 2カラムレイアウトの意図
  • セキュリティの基礎: エンコードと暗号化の違い

「小さなツールを作る」という経験は、これだけ多くの知識が詰まっています。一つのツールを完全に理解できると、それが他のすべての技術の土台になります。

ぜひツールを触りながらこの記事を読み返してみてください。

→ Base64 エンコーダー・デコーダーを使ってみる


ツール解説シリーズ:第1回・IP計算機 | 今ここ(第2回・Base64エンコーダー) | 第3回・chmod計算機 | 第4回・JSONフォーマッター | 第5回・Cronジェネレーター

この記事をシェアする

関連記事


CHECK IT OUT

Members Only

サブスク加入者限定の コンテンツを配信中

  • 毎月のAI・自動化トレンドレポート
  • クリエイター向け業務効率化テンプレート
  • ツール選定・SaaS比較まとめ(限定公開)
Discord サーバー & LINE 公式の両方で通知します
クリエイター・個人事業主向け 受付中

「これ自動化できないかな?」 そのアイデア、ITで実現できます。

業務の自動化・お客様向けツール開発・AI活用まで、クリエイター・個人事業主専門のITコンサルタントが対応します。まずは気軽にご相談ください。

LINEで相談 フォームで相談