Base64エンコード・デコードツール
入力した内容が保存・記録・共有されることはありません。
テキストをBase64に変換、またはBase64を元のテキストに戻します。Unicodeに正しく対応しているため、日本語や絵文字も文字化けせずに変換できます。
使い方
- エンコードまたはデコードを選びます。
- 入力欄にテキストまたはBase64文字列を貼り付けます。
- コピーボタンで結果をコピーします。
Base64は何のためにあるのか
Base64は、任意のバイト列を、どんなテキストの経路でも壊れない64種類の文字で書き直す方式です。3バイトずつ取り出し、その24ビットを6ビットずつ4つに分け、それぞれをA〜Z、a〜z、0〜9と2つの記号のいずれか1文字に対応させます。3バイトの入力に対して4文字を出力するので、改行を含めなくても元のデータより約33%大きくなります。
目的は伝送であって秘匿ではありません。Base64は、生のバイト列を壊してしまう経路のために設計されました。最上位ビットを削るメールシステム、特定の制御文字を命令として扱うプロトコル、プレーンテキストでなければならない形式などです。暗号化でも圧縮でもなく、エンコードされた内容は、デコードしようと思えば誰でも簡単に読めます。Base64の文字列を保護されたもののように扱うのは誤解であり、このデコーダーを使えばそれを簡単に実演できます。
パディングと2種類のアルファベット
入力が3バイト単位で割り切れない場合、出力の長さが4の倍数になるよう、1つか2つの=でパディングされます。パディングを省略して出力するものもありますが、正しい数は長さから決まるため、このデコーダーは入力を拒否せずパディングを補います。
標準のアルファベットは最後の2文字が+と/で、どちらもURL内で意味を持つため、エスケープすると%2Bと%2Fになり、クエリ文字列やファイル名では見づらく間違いのもとになります。そこでRFC 4648の5章は、代わりに-と_を使うURLセーフ版を定義しており、=もエスケープが必要なのでパディングは通常省略されます。JWTのすべてのセグメントで使われているのがこの形式です。このツールのエンコードでは両方を選べ、デコードでは貼り付けた文字列がどちらのアルファベットかを自動判定するので、指定する必要はありません。
Unicodeとbtoaの落とし穴
ブラウザには何十年も前からbtoa関数が組み込まれていますが、多くの人が思っているようには動きません。btoaはLatin-1を前提としており、入力のすべての文字のコードポイントが256未満でなければならず、それ以外があるとInvalidCharacterErrorを投げます。日本語を1文字、キリル文字の名前、絵文字を渡すだけで、そのまま失敗します。
最初に見つかりがちな回避策はエンコード前に文字列をescapeすることですが、これはASCII以外の文字を別のバイト列に変えてしまい、受け取る側では文字化けとしてデコードされます。正しい方法は、ここで使っているとおり、まずTextEncoderでテキストをUTF-8のバイト列に変換し、そのバイト列をエンコードすることです。だからこのツールでは、どんな文字体系でも往復して元のまま戻ります。
デコードはその逆を行い、推測はしません。デコードしたバイト列が有効なUTF-8でなければ、置換文字だらけの文字列を表示するのではなく、バイナリデータであることを伝えます。その場合、ペイロードはたいてい画像、アーカイブ、protobufメッセージ、暗号文のいずれかで、テキストとして読むのではなくバイト列として保存するのが正解です。
使うべきでない場面
Base64は何も保護しないので、秘密情報の保管には不向きです。大きなアセットの埋め込みにも既定の選択肢としては適していません。画像をdata URIにするとサイズが3分の1増え、それを含むドキュメントと切り離してキャッシュできず、解析が終わるまでページの処理を止めてしまいます。
Base64が本領を発揮するのは、小さくて扱いにくいケースです。PEM形式の証明書、署名、JSON本文内のバイナリフィールド、短いインラインアイコン、トークンのセグメントなどがそれにあたります。
3バイトが4文字になる
一度自分の手で計算してみると、この符号化は納得しやすくなります。ASCIIの3文字Manを例にとると、バイト値は77、97、110で、2進数では01001101、01100001、01101110です。この24ビットを並べ、8ビット3つではなく6ビット4つに区切ります。010011、010110、000101、101110です。それぞれを数値として読むと19、22、5、46になり、A〜Z、a〜z、0〜9、+、/というアルファベットで引きます。インデックス0がA、26がaです。結果はTWFuになります。
Base64の性質はすべてこの計算から導けます。1文字あたり6ビットだからアルファベットはちょうど64種類です。3バイトあたり4文字だから出力は3分の1大きくなります。そしてパディングがあるのは、最後のグループが足りない場合があるからです。余りが1バイトなら2文字と==、余りが2バイトなら3文字と=になります。
デコードはこれを逆にたどるだけです。だからこそ、長さが4の倍数でないBase64文字列は、パディングされているか、途中で切れているか、あるいは意図的にパディングを外すエンコーダーが作ったもののいずれかだとわかります。
実際のシステムで出会う場所
PEMファイル(証明書、CSR、秘密鍵)は、ヘッダー行とフッター行を付け、64文字ごとに改行を入れたBase64です。この行の長さはBase64の要件ではなくMIMEの慣習で、デコーダーは改行を無視することになっています。
HTTPのBasic認証は、username:passwordをBase64でエンコードしてAuthorizationヘッダーに載せます。平文のHTTPでBasic認証を使うことが、パスワードをそのまま送るのと同じである理由はまさにこれです。メールの添付ファイルは、1992年にMIMEが定義されて以来Base64を使ってきました。理由は当時から変わらず、メールサーバーが任意のバイト列を安全に運べるとは限らなかったからです。
data URIはファイル全体をドキュメントに埋め込みます。data:image/png;base64,に続けてペイロードを書く形式です。JSON APIは、バイナリを運ぶフィールドがあるときは必ずBase64を使います。JSONにバイナリ型がないからです。JWTの各セグメントはパディングなしのURLセーフ版を使い、Dockerの設定、Kubernetesのシークレット、多くのCIシステムは認証情報をBase64でエンコードして保存します。これは保管方法であって、保護ではありません。
サイズ、メモリ、大きなファイル
33%の増加は目立つコストですが、たいていは最も小さなコストです。Base64のテキストは元のバイト列より圧縮しにくくなります。符号化によって、圧縮アルゴリズムが利用するはずのバイト単位のパターンが壊れるからです。そのため、gzip圧縮したBase64のペイロードは、元データをgzip圧縮したものより大きくなるのが普通です。
ブラウザではメモリのほうが厳しい制約になります。ファイルをエンコードするにはバイト列と生成した文字列を同時に保持する必要があり、文字列はさらに3分の1大きいので、100MBのファイルでは送信前に数百MBを要することもあります。ファイルをチャンクに分けて順に符号化するストリーミングAPIならこれを避けられます。ただし各チャンクは3バイトの倍数にして、パディングが最後だけに現れるようにしてください。
大きなものについては、そもそも符号化しないのが良い答えであることがほとんどです。ファイルはmultipart form dataか生のボディとして送り、Base64はテキスト形式の中を通らなければならない小さく扱いにくい値のために取っておきましょう。
近い仲間のアルファベットとその存在理由
Base32は32文字を使い、出力は入力より60%大きくなります。割に合わないように聞こえますが、人が声に出して読んだり手で入力したりする必要があるときには話が別です。大文字小文字を区別せず、紛らわしい文字を避けており、TOTPのシークレットやTorのオニオンアドレスで使われています。
Base58は0、O、I、lと2つの記号を除き、目で見て写し間違えないようにしたものです。ビットコインのアドレスがよく知られた用途です。Base85(Ascii85)は4バイトを5文字に詰め込み、Base64より高密度ですが、多くの形式ではエスケープが必要になる記号を使います。PDFやPostScriptの中で主に生き残っているのはそのためです。
共通しているのは、どれも密度と経路の制約を天秤にかけているという点です。Base64が今の位置にいるのは、手間に見合うだけの密度があり、しかも最も広い範囲のテキスト経路で安全だからです。
渡されたペイロードを調べる
得体の知れない文字列を見たとき、まず確かめるべきは、それが本当にBase64かどうかです。手がかりは3つあります。長さが4の倍数か、末尾に=が1〜2個あること。文字が英字、数字、2種類の記号に限られていること。そしてデコードすると、意味不明なバイト列ではなく、読めるテキストか見覚えのあるファイルヘッダーが現れることです。
そのファイルヘッダーは、符号化された形のまま見分けられるようにしておくと便利です。保存する前に中身がわかります。デコードした結果が89 50 4E 47で始まればPNG、FF D8 FFならJPEG、50 4B 03 04ならzip(Office文書もこれに含まれます)、25 50 44 46ならPDFです。Base64の形では、iVBORw0KGgoで始まればPNG、/9j/ならJPEGで、どちらもAPIのペイロードやdata URIで頻繁に見かけます。
デコードしてもテキストにも既知のヘッダーにもならない場合、考えられるのは、URLセーフなBase64を標準のアルファベットでデコードしている、二重に符号化されている、あるいはBase64ではなく16進数やbase32である、のいずれかです。どれも一瞬で見分けられます。URLセーフな文字列にはマイナスかアンダースコアが含まれ、二重符号化されたものはデコードするとまたBase64らしき文字列になり、16進数は16種類の文字しか使いません。
よくある質問
- 日本語などのマルチバイト文字にも対応していますか?
- はい。入力はエンコード前にUTF-8へ変換されるため、日本語・中国語・韓国語・絵文字も正しく変換できます。多くのツールはブラウザのbtoa関数をそのまま使っており、Latin-1以外の文字でエラーになります。
- URLセーフなBase64とは何ですか?
- RFC 4648で定義された形式で、+を-に、/を_に置き換え、末尾の=を省略します。URLやファイル名にそのまま使えます。エンコード時にチェックを入れてください。デコードはどちらの形式も自動判別します。
- デコード結果がバイナリデータと表示されるのはなぜですか?
- Base64としては正しいものの、中身がUTF-8テキストではない場合です。画像やアーカイブ、暗号化データなどが該当します。文字化けを表示せず、状況をそのままお伝えしています。
- パディングの=は必要ですか?
- いいえ。=が不足していても自動的に補われます。貼り付けた文字列に含まれる空白や改行も無視されます。
- データはサーバーに送信されますか?
- いいえ。エンコードもデコードもすべてブラウザ内で実行されるため、データが端末外に出ることはありません。トークンや認証情報も安全に扱えます。
最終更新:
操作手順、期待した結果、実際の結果を記載してください。秘密情報や個人情報は削除してください。
