文字列やファイルをBase64でエンコードしたい、Base64の文字列を元に戻したいときは、openssl base64を使う。
$ echo -n "hello world" | openssl base64
aGVsbG8gd29ybGQ=
デコードするには-dを付ける。
$ echo "aGVsbG8gd29ybGQ=" | openssl base64 -d
hello world
実行例はUbuntu 24.04のOpenSSL 3.0.13のもの。
ファイルをエンコード・デコードする
-inで入力ファイル、-outで出力ファイルを指定する。省略すると標準入力と標準出力を使う。
$ openssl base64 -in image.png -out image.b64
$ openssl base64 -d -in image.b64 -out image-restored.png
バイナリファイルでも元のデータに戻る。
エンコード結果を1行にする
エンコード結果は64文字ごとに改行される。たとえば100バイトのデータをエンコードすると3行になる。
$ openssl base64 -in long.txt
YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh
YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh
YWFhYQ==
-Aを付けると、改行なしの1行で出力する。
$ openssl base64 -A -in long.txt
YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYQ==
環境変数やHTTPヘッダーなど、1行で扱いたい場所に値を渡す場合に使う。-Aなしの出力からtr -d '\n'で改行を取り除いても同じ結果になる。
1行のBase64をデコードする
-Aを付けずに1行の長いBase64をデコードすると、OpenSSL 3.0やLibreSSLではエラーにならず、何も出力されない。
$ openssl base64 -A -in long.txt | openssl base64 -d | wc -c
0
デコード時にも-Aを付ける。
$ openssl base64 -A -in long.txt | openssl base64 -d -A | wc -c
100
64文字ごとに改行された入力は、-Aなしでデコードできる。
文字列にエンコードすると改行が含まれる
echoは末尾に改行を付けるため、改行を含めた状態でエンコードされる。
$ echo "hello" | openssl base64
aGVsbG8K
$ echo -n "hello" | openssl base64
aGVsbG8=
aGVsbG8Kをデコードすると、末尾に改行を含むhelloが得られる。文字列だけをエンコードしたい場合は、echo -nかprintfを使う。
URLセーフなBase64にする
標準のBase64で使う+と/は、URLやファイル名に含めると特別な意味を持つ。openssl base64にURLセーフな出力のオプションはないため、trで置き換える。
$ printf '\xfb\xff\xfe' | openssl base64
+//+
$ printf '\xfb\xff\xfe' | openssl base64 | tr '+/' '-_' | tr -d '='
-__-
デコードするときは、逆の置き換えをしてからopenssl base64 -dに渡す。
$ echo '-__-' | tr '_-' '/+' | openssl base64 -d | od -An -tx1
fb ff fe
=を取り除いた値は、デコード前に=を補う必要がある。補い方は次の節を参照。
デコード結果が空になる場合
openssl base64 -dは、入力が不正でもエラーメッセージを表示せず、終了コードも0のままである。デコード結果が空になる場合は、以下を疑う。
末尾に改行がない
入力の末尾に改行がないと、OpenSSL 3.0、3.5、3.6、LibreSSLのいずれでも何も出力されない。
$ printf 'aGVsbG8=' | openssl base64 -d
$ printf 'aGVsbG8=\n' | openssl base64 -d
hello
末尾に改行のない入力を渡す場合は-Aを付ける。
$ printf 'aGVsbG8=' | openssl base64 -d -A
hello
=によるパディングがない
パディングの=が取り除かれたBase64は、デコードできず何も出力されない。
$ echo 'aGVsbG8gd29ybGQ' | openssl base64 -d
4の倍数の長さになるまで=を補うと、デコードできる。
$ s='aGVsbG8gd29ybGQ'
$ while [ $(( ${#s} % 4 )) -ne 0 ]; do s="$s="; done
$ echo "$s" | openssl base64 -d
hello world
Base64以外の文字を含む
Base64に使えない文字が1つでも含まれていると、正しい行も含めて何も出力されない。
$ printf 'aGVsbG8=\n!!!\n' | openssl base64 -d
バージョンによる違い
OpenSSL 3.5では、-Aなしでも1行の長いBase64をデコードできる。OpenSSL 3.0やmacOS標準の/usr/bin/openssl(LibreSSL 3.3.6)では、前述の通り何も出力されない。デコード時に-Aを付けておけば、どのバージョンでも同じように動く。
openssl base64はopenssl enc -base64やopenssl enc -aと同じ動作である。
$ echo -n hi | openssl enc -a
aGk=
base64コマンドとの使い分け
LinuxやmacOSにはbase64コマンドもある。Base64のエンコード・デコードだけならbase64コマンドが簡単である。
$ echo -n "hello world" | base64
aGVsbG8gd29ybGQ=
GNU coreutilsのbase64は、76文字ごとに改行する。改行なしにするには-w0を付ける。
$ echo -n "hello world" | base64 -w0
aGVsbG8gd29ybGQ=
base64コマンドがない環境や、opensslを使う他の処理とまとめたいスクリプトでは、openssl base64を使う。
