base64コマンドとpadding文字

1 min read読了の目安(約1500字

tl;dr

mac版base64ではpaddingの後の文字列は処理されないよ。
パイプとかで処理する時注意したほうがいいよ。

base64

バイナリをアルファベット(a-zA-Z)、数字(0-9)、いくつかの記号(+/=)でエンコードするフォーマットです。画像などのバイナリデータを、JSONなどテキストで送りたい時に使えます。

padding

base64では24bit毎に4文字に変換します。入力が足りず4文字にならない時に、最後に付ける「=」がpaddingです。

base64コマンド

Linuxやmacではbase64コマンドでbase64のエンコード・デコードを行えます。
特にmacでは、組み込みのbase64コマンドと、GNU版のbase64コマンド(gbase64)コマンドの二種類を使うことが出来ます(※)。
用途・基本的な機能は同じですが、オプションや挙動が少し違います。

※ coreutilsのインストールが必要

base64コマンドのpaddingの扱いの違い

以下の違いがありそうです。

  • GNU版base64(gbase64)では、paddingの後の文字列も処理される
  • mac版base64では、paddingの後の文字列は処理されない

言及しているWebページを見つけられていないので、何かご存知の方は情報ください…

元データ

「ABCDEFG」、「hogehoge」、「hoge」の三行をbase64エンコードしたファイルです

QUJDREVGRwo=
aG9nZWhvZ2UK
aG9nZQo=

GNU版base64(gbase64)

cat buzz | gbase64 -d                                                     
ABCDEFG
hogehoge
hoge

mac版base64

「ABCDEFG」の一行だけ出力されていることに注目してください。

cat buzz | base64 -D                                                     
ABCDEFG

どんな影響が?

例えば、

  1. APIからbase64・paddingを含むJSONを取得
  2. base64を含む一部分だけを抽出
  3. base64コマンドでデコード

する時、一連の流れをパイプで繋ぐと、データの見落としやロストが発生しそうです。

回避

ループ

一番簡単・汎用的だと思います。

#!/bin/bash
while read line
do
    echo $line | base64 -D
done < buzz
./decode.sh
ABCDEFG
hogehoge
hoge

jqコマンド

JSONに含まれるbase64をデコードしたい時に限れば、jqコマンドは組み込みでbase64のエンコード・デコードができます。

入力データ

cat buzz.json 
[
    "QUJDREVGRwo=",
    "aG9nZWhvZ2UK",
    "aG9nZQo="
]
cat buzz.json | jq  ".[] | @base64d"
"ABCDEFG\n"
"hogehoge\n"
"hoge\n"