Base64・文字コードを解読する
ブラウザ開発者ツール編から一歩進み、CTF「暗号編」の入り口へ。Base64エンコード・文字コード・URLエンコードという3つの基本的な「変換」を見破る力を身につけます。
📋 目次
🔢 Base64とは何か|「暗号」ではなく「エンコード」
パッと見は暗号文っぽいが、誰でも一瞬で元に戻せる
最重要ポイント:Base64には「鍵」が存在しない
Base64は暗号化(Encryption)ではなく、符号化(Encoding)です。暗号化はパスワードや鍵がなければ元に戻せませんが、Base64には鍵という概念がそもそもありません。変換ルールが完全に公開されているため、だれでも一瞬で元の文字列に戻せます。「Base64だから安全」と思ってデータを保存するのは大きな間違いです。
Base64は、画像やファイルのようなバイナリデータを、メールやURL・JSONなど「印字可能な文字(ASCII文字)しか扱えない場所」でも安全に送れるようにするための変換方式です。具体的には、3バイト(24ビット)のデータを6ビットごとに4つに分割し、それぞれをA-Z・a-z・0-9・+・/の64種類の文字に対応させます。足りない分は=でパディング(穴埋め)します。
Base64の見分け方
文字列がA-Z・a-z・0-9・+・/のみで構成され、長さが4の倍数で末尾に=または==が付いていれば、Base64である可能性が非常に高いです。CTFでは「読めない文字列=とりあえずBase64を疑う」が鉄則です。
💻 ConsoleでBase64を解読する(atob/btoa)
ブラウザに標準搭載された変換関数
ブラウザのJavaScriptには、Base64を変換するための関数が標準で用意されています。第2話で学んだConsoleタブを開いて、すぐに試してみましょう。
| 関数 | 働き | 実行例 |
|---|---|---|
atob(str) | Base64文字列 → 元の文字列にデコード | atob('SGVsbG8=') → "Hello" |
btoa(str) | 文字列 → Base64にエンコード | btoa('Hello') → "SGVsbG8=" |
atobは日本語など2バイト以上の文字でエラーになることがある
atob()はASCII文字(1バイト文字)を前提にしているため、日本語などのマルチバイト文字を含む文字列をBase64化したものをデコードすると文字が崩れたりエラーになることがあります。その場合はdecodeURIComponent(escape(atob(str)))のような追加処理が必要になりますが、入門編ではまず英数字のみのケースに慣れましょう。
🔤 文字コードとUnicode(charCodeAt/fromCharCode)
すべての文字は単なる「数字」である
コンピューターの内部では、文字は数字(コードポイント)として管理されています。「A」は65、「a」は97、「0」は48……というように、すべての文字に固有の番号が振られています(Unicode/ASCII)。この対応関係を操作できると、文字を数値配列として隠す簡単な暗号パズルも解けるようになります。
| 文字 | 10進コード | 16進コード |
|---|---|---|
A | 65 | 0x41 |
a | 97 | 0x61 |
0 | 48 | 0x30 |
{ | 123 | 0x7B |
} | 125 | 0x7D |
_(アンダースコア) | 95 | 0x5F |
2つの相互変換関数を覚えよう
'A'.charCodeAt(0) は文字 → コード番号(結果:65)。String.fromCharCode(65) は コード番号 → 文字(結果:'A')。CTFでは[67,84,70,123,...]のような数字の配列がフラグの正体であることがよくあります。ConsoleでString.fromCharCode(67,84,70,123)のように実行すれば一瞬で復元できます。
🔗 URLエンコードも解読する(encodeURIComponent)
%から始まる謎の文字列の正体
URLには使ってはいけない文字(スペース・{・}・?・&・日本語など)があります。これらを安全に送るため、パーセント記号+16進数の文字コードという形式に変換するのがURLエンコード(パーセントエンコーディング)です。例えば{(コード123=16進0x7B)は%7Bに変換されます。
| 関数 | 働き | 実行例 |
|---|---|---|
encodeURIComponent(str) | 文字列をURLエンコード | encodeURIComponent('CTF{x}') → "CTF%7Bx%7D" |
decodeURIComponent(str) | URLエンコードされた文字列を元に戻す | decodeURIComponent('CTF%7Bx%7D') → "CTF{x}" |
CTFでは「多重エンコード」が頻出
実際の問題では、Base64・URLエンコード・文字コード変換などが2段、3段と重ねて使われることがあります。「とりあえずatobしてみる」→「結果に%が含まれていたらdecodeURIComponentしてみる」というように、見た目の特徴から手法を推理して順番に試すのがCTFの基本戦略です。
🧩 5分CTFチャレンジ:多重エンコードされた通信を解読せよ!
2段階のデコードでフラグへ到達する
下の「傍受した通信ログ」には、何らかの方式でエンコードされた文字列が記録されています。Consoleタブを開き、適切な関数を使ってデコードしてください。1回のデコードでは終わらないかもしれません。
チャレンジの手順
① 下のコードをコピーする → ② F12 → Consoleタブを開く → ③ atob('コピーした文字列') を実行する → ④ 結果に%記号が含まれていたら、それをさらにdecodeURIComponent(...)でデコードする → ⑤ 完成したフラグを入力フォームへ!
ENCODED PAYLOAD:
Q1RGJTdCQjRTM182NF9EM0MwRDNEJTdE
通信ログをデコードして得られたフラグを入力してください。フォーマットは CTF{...} です。
ログの文字列はアルファベットと数字、=で終わっています。Base64の特徴です。Consoleでatob('ログの文字列')を実行してみましょう。
atobした結果には%7Bや%7Dのような記号が含まれているはずです。これはURLエンコードされた{と}です。その文字列をdecodeURIComponent(...)に渡すと、最終的なフラグが得られます。
📝 まとめ+FAQ+次回予告
今回のポイントを振り返ろう
第10話では、Base64エンコード・文字コード・URLエンコードという3つの基本的な「変換」を学びました。これらはいずれも暗号ではなく公開された変換ルールにすぎず、atob・String.fromCharCode・decodeURIComponentという3つの関数で誰でも元に戻せます。CTFの「暗号編」はここから始まります。
・Base64は暗号化ではなく符号化(誰でも元に戻せる)
・Base64らしき文字列はatob()でデコードする
・文字コードの数字配列はString.fromCharCode()で文字列に戻せる
・%XX形式の文字列はURLエンコード=decodeURIComponent()でデコード
・CTFでは複数の変換が重ねられることが多いので順番に試す
Q. Base64でエンコードしたデータは安全ではないのですか?
その通りです。Base64には鍵が存在しないため、誰でも一瞬で元に戻せます。パスワードや個人情報をBase64化しただけで「暗号化した」と表現するシステムを見かけたら、それは重大なセキュリティ上の誤りです。本当に保護したいデータには、AESなどの本物の暗号化アルゴリズムが必要です。
Q. Base64の文字列に+や/が含まれないことがあるのはなぜですか?
URLの中で安全に使えるよう、+を-に、/を_に置き換えた「URL-safe Base64」という変種が使われることがあります。デコードする際は通常のatobがエラーになる場合、まずこれらの文字を元に戻してから試してみてください。
Q. 1つの問題で何重にもエンコードされていたらどう見分けますか?
デコードした結果をよく観察してください。英数字+/=のみならBase64、%を含むならURLエンコード、数字の配列ならcharCode、まだ読めない文字列ならさらに別の変換が重なっている可能性があります。「1回デコードしたら終わり」と思い込まず、結果の見た目で次の手法を判断する練習が大切です。
Q. オンラインのBase64デコードツールを使ってもいいですか?
学習段階ではブラウザのConsoleでatob/btoaを使う方法をおすすめします。オンラインツールは便利ですが、本番のCTF問題でフラグを含む文字列を信頼できない外部サイトに貼り付けるのは情報漏洩のリスクがあります。ブラウザ標準の関数だけで完結できることを知っておくと安心です。
シーザー暗号・XOR暗号を解く
文字を数字としてずらす・反転させる、古典的だけど奥が深い暗号の仕組みと、CTFでの解読テクニックを体験します。
📚 参考情報
- MDN Web Docs「Base64 のエンコードとデコード」(Mozilla)
- RFC 4648 — The Base16, Base32, and Base64 Data Encodings
- MDN Web Docs「encodeURIComponent()」(Mozilla)


コメント