Mac/開発環境
PR

【Macユーザー向け】base64 デコード時にパディングがなくてエラー?解決方法まとめ

saratogax
記事内に商品プロモーションを含む場合があります

Mac のターミナルで base64 を使ってエンコード/デコードする機会は意外と多いですよね。

しかし、Linux と違って macOS の base64 コマンドには --ignore-garbage オプションがありません。

そのため、パディング(末尾の =)が省略された base64 文字列をデコードしようとすると、エラーになってしまうことがあります。

この記事では、Mac環境でパディングがない base64 を安全にデコードする方法を3つ紹介します。

問題:macOS の base64 はパディングなしに弱い

たとえば、以下のような base64 文字列をデコードしようとすると、

echo 'YWJjZA' | base64 -D

macOS では以下のようなエラーが出てしまいます。

base64: invalid input

JWT からペイロード部分を抜き出して、そこを base64 デコードして jq コマンドで JSON 文字列を解析したい。

そんな場合に、この問題によく遭遇したまま放置してました。

echo 'YWJjZA' | base64 -D | jq .data.hoge

解決策①:パディングを補ってからデコード(おすすめ)

base64 は 4文字単位で構成されるため、長さが 4 の倍数になるよう = を追加することで正常にデコードできます。

この方法は手軽で、macOS 標準の base64 コマンドでそのまま使えるのが魅力です。

base64_str="YWJjZA"

# 4の倍数にするため = を補完
padded_str=$(printf "%s" "$base64_str" | awk '{ while (length % 4 != 0) $0=$0"="; print }')

echo "$padded_str" | base64 -D

解決策②:GNU coreutils の gbase64 を使う

Linux でおなじみの GNU 版 base64 を使いたい場合は、Homebrew 経由で GNU coreutils をインストールします。

brew install coreutils

すると、gbase64 という名前で GNU 版の base64 が使えるようになります。

ただし注意したいのが --ignore-garbage の役割です。これは base64 の文字集合に含まれない文字(改行や空白などのゴミ)を読み飛ばすオプションで、パディング不足そのものは補完しません。パディングのない文字列をそのまま渡すと、gbase64 でも同じく base64: invalid input になります。

複数行に折り返された base64 など「ゴミ文字が混ざった入力」をまとめてデコードしたいときに便利なオプション、という位置づけです。パディング不足に対しては、解決策①と同じく = を補ってから渡します。

# --ignore-garbage は改行やゴミ文字を無視する(パディングは補完しない)
# 4の倍数になるよう = を補ってから gbase64 に渡す
padded_str=$(printf '%s' 'YWJjZA' | awk '{ while (length % 4 != 0) $0=$0"="; print }')
echo "$padded_str" | gbase64 --ignore-garbage --decode

解決策③:Python で柔軟にデコード

もしシェルスクリプトなどで複雑な処理が必要な場合は、Python を使う方法もおすすめです。

こちらも = を自動的に補ってからデコードしてくれるので安心です。

#!/usr/bin/env python3
import sys
import base64

def pad_base64(s):
    """base64文字列の長さが4の倍数になるようにパディングを追加"""
    return s + '=' * ((4 - len(s) % 4) % 4)

def main():
    if len(sys.argv) > 1:
        # 引数からデコード対象の文字列を取得
        input_str = sys.argv[1]
    else:
        # 標準入力から取得
        input_str = sys.stdin.read().strip()

    padded = pad_base64(input_str)

    try:
        decoded_bytes = base64.b64decode(padded)
        decoded_str = decoded_bytes.decode('utf-8')
        print(decoded_str)
    except Exception as e:
        print(f"デコードに失敗しました: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()

まとめ

今回は base64 デコード時のパディングについて、以下の 3 つの方法を紹介しました。

  • Mac 標準機能だけで手動で補う
  • GNU coreutils の gbase64 を使う(--ignore-garbage は改行などの除去用で、パディング不足には = の補完が必要)
  • Pythonスクリプトで処理

こんな場面に遭遇した方にオススメって私ですが・・・。

  • API などから取得した base64 がパディングされていない
  • Mac で bash スクリプトを組んでいて base64 を扱う
  • Linux との挙動の違いに戸惑っている

macOS の base64 はシンプルですが、Linux のような柔軟性がないぶん、少し工夫が必要です。

本記事で紹介した方法で、パディングに関する問題をスマートに解決してみてください!

Kotlin での Base64 エンコード・デコードは、以下の記事でまとめています。

あわせて読みたい
【Kotlin入門】Base64エンコードとデコード(getEncoder, getDecoder)
【Kotlin入門】Base64エンコードとデコード(getEncoder, getDecoder)
ABOUT ME
saratoga
saratoga
フリーランスエンジニア
仕事にも趣味にも IT を駆使するフリーランスエンジニア。技術的な TIPS や日々の生活の中で深堀りしてみたくなったことを備忘録として残していきます。
記事URLをコピーしました