base64 コマンド入門 - エンコード・デコードの基本

base64 コマンド入門 - エンコード・デコードの基本

この記事でわかること

  • base64文字列やファイルをエンコード / デコード できる
  • echo改行が混ざる落とし穴 を避けられる
  • -w(折り返し)や -d(デコード)など よく使うオプション が分かる
  • base64 は暗号化ではない」という 最重要ポイント を理解できる

対象読者:Linux 入門者、API トークンやメール添付で base64 文字列を見て「これ何?」と思った方

導入:リナの謎の文字列事件

リナ: ライニー先輩、設定ファイルに SGVsbG8gV29ybGQ= みたいな謎の文字列があったんですけど、これ何ですか? パスワードを暗号化したやつ?
ライニー先輩: お、いいところに気づいたね。それは base64(ベースろくじゅうよん)でエンコードされた文字列だよ。でも一つ大事なこと言っておくと、それは 暗号化じゃない んだ。
リナ: え、暗号化じゃない? じゃあ中身は読めちゃうんですか?
ライニー先輩: そう。base64 -d を通すだけで誰でも元に戻せる。だから秘密を守る用途には使えない。今日はその base64 の基本と、なぜ存在するのかを一緒に見ていこう。

結論を先に

  • base64 = バイナリを ASCII 文字だけで表現 する変換(A-Z, a-z, 0-9, +, /, =)
  • エンコードは base64、デコードは base64 -d
  • 暗号化ではない。誰でもデコードできる。秘密の保護には使わない

1. base64 とは何か?

結論: base64 はバイナリデータを 64 種類の ASCII 文字に変換する方式。暗号化ではなく「運搬用の包装」。

リナ: そもそも、なんでわざわざこんな変換が必要なんですか?
ライニー先輩: いい質問。メールや一部のプロトコルは テキスト(ASCII 文字)しか安全に運べない ことがあるんだ。画像みたいなバイナリをそのまま流すと途中で壊れることがある。
リナ: なるほど、文字に変換しておけば安全に運べると。
ライニー先輩: その通り。base64任意のデータを 64 種類の文字だけで表現 する。だから「暗号」じゃなくて「運搬用の包装」だと思うといい。中身は隠れていないけど、安全に運べる形になる。

base64 が使われる場所

  • メールの添付ファイル(MIME)
  • HTTP の Basic 認証ヘッダー
  • 設定ファイル・JSON に埋め込むバイナリ(画像・証明書など)
  • data: URL(HTML に画像を直接埋め込む)

2. 文字列をエンコードしてみる

結論: echo -n でパイプして base64 に渡す。-n を付けないと末尾の改行まで一緒にエンコードされる。

ライニー先輩: まずは文字列を実際にエンコードしてみよう。Hello World を変換するよ。
リナ: パイプ(|)で base64 に渡すんですね。
$ echo -n "Hello World" | base64
SGVsbG8gV29ybGQ=

echo -n-n を忘れない

echo はデフォルトで 末尾に改行を付ける-n なしだと改行 1 文字(\n)まで一緒にエンコードされ、結果が変わってしまう。

リナ: -n を付けないとどうなるんですか?
ライニー先輩: 試すと一目瞭然だよ。改行が混ざると最後の数文字が変わる。
$ echo "Hello World" | base64
SGVsbG8gV29ybGQK

SGVsbG8gV29ybGQ=SGVsbG8gV29ybGQK の違い

末尾が =(改行なし)か K(改行 \n を含む)かで変わる。トークンやパスワードを base64 化する時、この改行混入は トラブルの定番 なので必ず echo -nprintf を使う。

# printf は改行を付けないので -n の付け忘れを防げる
$ printf '%s' "Hello World" | base64

3. デコードしてみる

結論: base64 -d(または --decode)で元に戻す。誰でも実行できるので秘密保護にはならない。

ライニー先輩: 次は逆。さっきの SGVsbG8gV29ybGQ= を元に戻してみよう。-d を付けるだけだよ。
リナ: デコードって特別な鍵とか要らないんですか?
ライニー先輩: 要らない。だからこそ「暗号化じゃない」って最初に言ったんだ。手元にコマンドさえあれば誰でも中身が見える。
$ echo "SGVsbG8gV29ybGQ=" | base64 -d
Hello World

-d--decode は同じ

base64 -d でも base64 --decode でも動く。短い -d が一般的。

リナ: 冒頭の設定ファイルの謎の文字列も、これで中身が読めちゃうってことですか...
ライニー先輩: そういうこと。だから API キーやパスワードを base64 にしただけで「隠した」と思ってはいけない。隠したいなら暗号化(openssl など)が必要だよ。

4. ファイルをエンコード・デコードする

結論: 引数にファイル名を渡せばエンコード、-d で出力をファイルにリダイレクトすれば復元できる。

ライニー先輩: 文字列だけじゃなくて、ファイルもそのまま渡せる。画像や証明書みたいなバイナリも変換できるよ。
# ファイルをエンコードして .b64 に保存
$ base64 image.png > image.png.b64

# .b64 をデコードして元のファイルに戻す
$ base64 -d image.png.b64 > restored.png
リナ: 戻したファイルって、本当に元と同じなんですか?
ライニー先輩: いい着眼点。diffmd5sum で確認できるよ。一致すれば完全に復元できている証拠だ。
# 元ファイルと復元ファイルが同一か確認
$ diff image.png restored.png && echo "OK: 完全一致"
OK: 完全一致

サイズは約 1.33 倍に増える

base64 は 3 バイトを 4 文字に変換するので、エンコード後は 元の約 4/3(約 33% 増) のサイズになる。容量に余裕がない場所で大きいファイルを base64 化する時は注意。

5. 折り返し(改行)を制御する -w

結論: base64 は既定で 76 文字ごとに改行を入れる。1 行にしたいなら -w 0 を使う。

リナ: 長いファイルをエンコードしたら、途中で何回も改行されてました。これって普通ですか?
ライニー先輩: 普通だよ。base64デフォルトで 76 文字ごとに改行(折り返し) を入れる。メールの MIME 規格に合わせた仕様なんだ。
リナ: でも 1 行で欲しい時もありますよね。トークンを 1 行で扱いたいとか。
ライニー先輩: その時は -w 0-w は「wrap(折り返し)」で、0 を指定すると 折り返しなし になる。
# 折り返しなし(1 行で出力)
$ base64 -w 0 image.png > oneline.b64

# 40 文字ごとに折り返す
$ echo -n "Hello World, this is a longer text" | base64 -w 40

macOS の base64 には -w がない

-w は GNU coreutils(Linux 標準)のオプション。macOS(BSD 版)の base64 には -w がなく、折り返し制御の方法が異なる。この記事は Linux(GNU coreutils) を前提にしている。

6. よくある落とし穴

結論: 「暗号化と勘違い」「echo の改行混入」「デコード時の不正文字」が三大つまずきポイント。

ライニー先輩: 最後に、初心者がハマりやすいポイントを 3 つまとめておくね。

落とし穴 2:echo の改行混入

2 章 で見た通り、echo -n を忘れると改行までエンコードされる。トークンを base64 化したのに認証が通らない時、まずこれを疑う。

落とし穴 3:デコード時の invalid input

コピペでスペースや余計な文字が混ざると base64: invalid input が出る。-i--ignore-garbage)で アルファベット以外の文字を無視 してデコードできる。

# 改行やスペースが混ざっていても無視してデコード
$ base64 -d -i messy.b64

安全テンプレ(コピペ用)

# 文字列をエンコード(改行を入れない)
printf '%s' "テキスト" | base64

# 1 行でエンコード(折り返しなし)
base64 -w 0 file.bin

# デコード
echo "SGVsbG8=" | base64 -d

7. ミニ課題:自分の環境で試そう

結論: エンコード・往復確認・改行の違いの 3 問で base64 の挙動を体に覚えさせる。

ライニー先輩: 知識を定着させるために、自分の環境で次の課題をやってみよう。

課題 1:自分の名前を base64 でエンコードしてみる(改行を入れずに)

課題 2:課題 1 の結果を base64 -d でデコードし、元に戻ることを確認する

課題 3echo -n "test"echo "test" をそれぞれエンコードし、結果が違う理由を 1 行で説明する

課題 1 のヒント
printf '%s' "あなたの名前" | base64

printf '%s'echo -n を使えば末尾の改行が混ざらない。

課題 2 のヒント
echo "(課題1の出力)" | base64 -d

元の名前がそのまま表示されれば往復成功。

課題 3 のヒント

echo はデフォルトで末尾に改行(\n)を付ける。echo "test"test\n(5 バイト)、echo -n "test"test(4 バイト)をエンコードするため、結果の base64 文字列が異なる。

次に読む