エンコード、ハッシュ、暗号化はそれぞれ別物
このページで起こる誤解のほとんどは、この3つを同じものとして扱うことから生まれます。だから、きちんと区別しておく価値があります。
エンコードは元に戻せるもので、秘密は含まれません。Base64は、メールの添付ファイル、データURI、JSON文字列など、テキストしか受け付けない経路でバイナリデータを運ぶためのものです。3バイトごとに4文字で表すので、結果は常に約3分の1大きくなります。鍵はありません。文字列を見た人なら誰でも、当サイトを含め、一手でデコードできます。Base64はセキュリティではなく、難読化と呼べるものでもなく、見ようとする人から何かを隠す手段でもありません。パーセントエンコードはURL向けの同じ種類のもので、もう1つのよくあるバグの原因でもあります。クエリ文字列に入れる1つの値をエンコードすることと、組み立て済みのURL全体を整えることは別の操作です。URLの構造を作る&、=、?、/をエスケープするのは前者だけだからです。これを間違えると、「Smith & Sons」は1つの値ではなく2つのパラメーターとしてサーバーに届きます。
ハッシュは一方向で、こちらにも鍵はありません。ハッシュはどんな入力からも固定長の指紋を作り、元に戻す方法はありません。暗号化されているからではなく、情報そのものが失われているからです。できるのは、入力を推測して比べることだけです。そしてそれこそが、MD5、SHA-1、SHA-256がパスワードの保存に向かない理由です。計算が速く、グラフィックカードなら1秒に数十億回計算でき、盗まれたハッシュの表はその速さで解読されます。パスワードには、意図的に遅く、ソルトを使う関数、つまりbcrypt、scrypt、Argon2が必要です。それとは別の理由で、MD5とSHA-1は破られています。同じハッシュを持つ2つの異なるファイルを意図的に作れるようになったため、どちらもファイルが期待どおりのものだと証明することはできません。ただし、ダウンロード中に偶然壊れたファイルを見つける用途なら、どちらもまだ問題なく使えます。
鍵を持つのは暗号化だけで、これらのツールはどれも暗号化を行いません。これは見落としではありません。暗号化を正しく行うには鍵の管理が必要で、Webページは鍵を置く場所としてふさわしくないからです。
JWTは署名されているのであって、暗号化されてはいません。これはしょっちゅう人をつまずかせます。トークンのヘッダーとペイロードはBase64URLで、トークンを持っている人なら鍵なしで誰でも読めます。署名はトークンの改ざんを防ぎますが、読まれることは何も防がないので、機密情報をペイロードに入れてはいけません。したがって、トークンをデコードしても、そのトークンについて何も証明されません。誰でも好きなクレームを書いてBase64にできるからです。検証とは、発行者の鍵で署名を計算し直すことで、それはサーバーが行う作業であり、Webサイトが決して求めてはならないものです。そのため当サイトのデコーダーは検証済みであるかのような表示を一切せず、問題を示す形に警告を出します。期限切れのトークン、有効期限がまったくないトークン、そしてアルゴリズムが「none」のトークンです。最後のものは珍しい現象ではなく、文書化された認証回避の手口です。
JSONには、ほとんどの整形ツールが気づかないまま踏み込む数値精度の限界があります。JSON自体は数値の大きさに制限を設けていませんが、JavaScriptの数値は64ビット浮動小数点数なので、整数が正確に保たれるのは9,007,199,254,740,991までです。TwitterのポストID、DiscordのSnowflake、64ビットのデータベースキー、銀行の口座番号はこれより大きく、よくある1行の整形処理(パースしてから文字列化)を通すと末尾の桁が変わってしまいます。結果はそれらしい数値に見えるため、そこが危険なのです。7205759403792793600は、何の知らせもなく7205759403792793000になります。当サイトのJSONツールは、貼り付けたとおりの桁で再シリアライズし、保護した数値がいくつあったかを表示します。
UUIDのバージョンは、どう作られたかを表すもので、何を保証するかではありません。UUIDを登録したり一意性を強制したりする仕組みはなく、一意性は確率的なものです。バージョンが示すのは、ビットがどこから来たかです。バージョン4は、ブラウザの暗号用乱数生成器による122ビットのランダム値で、推測できないため、リセット用リンク、招待コードなど秘密にすべきものに適しています。一方、データベースのキーには向きません。ランダムなキーはソート済みインデックスの中に散らばり、断片化させるからです。バージョン7は先頭に48ビットのミリ秒単位のタイムスタンプを置くため、自動採番の整数と同じようにキーがインデックスの末尾に追加され、しかも世界中で一意なままです。その代わり、v7のUUIDを持っている人には、作成された日時がミリ秒単位ではっきり分かってしまいます。
ブラウザが本当に適さない場面
この13のツールは、どれもどこにも何も送信しません。リクエストは発生せず、何も記録されず、ネットワークを切断してもページは動き続けます。だからこそ、顧客データだらけのAPIレスポンスや、誰にもメールで送らないようなトークンにも使えるのです。これが、これらのツールを使う正直な理由です。ここからは、使わない方がよい正直な理由を挙げます。
本番環境で有効な秘密情報をWebページに貼り付けるのは、身につけない方がよい習慣です。このページも例外ではありません。当サイトのプライバシーに関する説明は事実ですが、あなたを守るのは説明ではなく、コードの振る舞いです。どんなWebページに対しても、信じるのではなく確かめるのが唯一賢明な態度です。確かめるのに手間はかかりません。ページを読み込んだあとにインターネットを切断し、これらのツールが動き続けるのを見てください。サーバーが必要なツールなら止まるはずです。そして、まだ有効な認証情報を、中身を確認できない場所にすでに貼り付けてしまったなら、正しい対応はあれこれ考えることではなく、その認証情報をローテーションすることです。今まさに有効なトークンなら、ローカルでデコードする方が、当サイトを含めどんなWebサイトよりも良い習慣です。使っている言語のBase64関数や、シェルで2行書くだけで済みます。
スキーマの検証。当サイトのJSONツールとXMLツールが確認するのは文書が整形式かどうかで、スキーマに合っているかどうかは別の問題です。JSON SchemaやXSDで検証するにはスキーマファイルを取得して適用する必要があり、それはこれらのページがあえて一切行わないネットワークリクエストです。JSON Schemaにはajv、XSDやDTDにはxmllintを使ってください。どちらも無料で、Webページよりもずっと上手にこなします。
本当に大きなもの、ストリーミングが必要なもの。文書は丸ごとメモリに保持され、整形中は2重に保持されることもあるので、上限はタブです。数MBなら一瞬ですが、数百MBとなるとそうはいきません。jqはどのブラウザでも開けない数GBのJSONファイルもストリーミングで処理でき、ripgrepは1つのファイルを貼り付けるより速くリポジトリ全体を検索します。ハッシュ生成にはこの制限がより厳しく当てはまります。ブラウザの暗号機能には逐次的なダイジェスト計算がないため、ファイル全体が一度にメモリに収まらなければなりません。DVDイメージは失敗しますが、sha256sum、shasum、certutilなら何事もなくストリーミングで処理します。
自動化とCI。これらは人がクリックしたときに動きます。リポジトリ内の全ファイルの整形、テスト用データへの1万個のUUIDの生成、パイプラインでのJSONチェックはスクリプトの仕事です。jq、xmllint、uuidgen、openssl、base64コマンドは、ほとんどのマシンにすでに入っています。
署名されたものの検証全般。署名の検証、証明書チェーン、秘密鍵を必要とする処理は、保守されているライブラリを使ってサーバー上で行うべきです。このページはトークンが何を主張しているかは教えますが、トークンが本物だとは決して言いません。鍵なしでそれができると言うサイトは信用しないでください。
似た名前のツールの選び方
JSON整形とJSON構文チェック。パーサーは同じで、問いが違います。整形は、すでにパースできる文書を読み、形を整えるためのものです。インデントを付ける、圧縮する、大きな数値をそのまま保つ。構文チェックはパースできない文書のためのもので、行、列、問題の文字とその下のキャレット、そしてよくある4つの原因のどれに当たるかを表示します。「Unexpected token」を前に途方に暮れているなら、構文チェックの方です。XML整形とXML構文チェックも同じ分担です。
Base64デコードとJWTデコード。JWTはBase64URLの3つの部分でできているので、汎用のデコーダーでも各部分は見られます。JWTのページはそれを分割し、JSONを整形し、有効期限・発行日時・有効開始日時のクレームをUnixタイムスタンプからお使いのタイムゾーンの実際の日時に変換し、登録済みクレームにラベルを付け、期限切れやアルゴリズム「none」について警告します。Base64のデータには汎用のデコーダーを、トークンにはJWTのページを使ってください。
Base64エンコードとURLエンコード。どちらも「安全な」テキストを作りますが、仕事は別です。Base64は任意のバイト列をテキストに変換し、サイズは33%増えます。しかも標準のBase64はURLではまったく安全ではありません。+、/、=はどれもURLの中で意味を持つからで、そのためにBase64URLがあります。パーセントエンコードは読めるテキストを読めるまま残し、URLを壊すものだけをエスケープします。検索語、メールアドレス、リダイレクト先にはこちらが適しています。ファイル全体をクエリ文字列用にエンコードしているなら、たいていはリクエストボディにすべきだったというサインです。
ハッシュ生成とUUID生成。ハッシュは入力から導かれるので、同じ入力からは常に同じ値が得られます。それが指紋たるゆえんで、ダウンロードの検証や同一内容の重複排除に役立ちます。UUIDは何とも関係のない新しいランダム値なので、繰り返されることはありません。同じ内容に同じ識別子が欲しいならハッシュを、新しい識別子が欲しいならUUIDを生成してください。
QRコード作成とバーコード作成。QRは2次元の格子で、URL、Wi-Fiの接続情報、電話番号など任意のテキストを保持でき、スマートフォンのカメラで読み取ります。バーコードのページが作るのは、小売や物流で使われる1次元のコードです。EAN-13、EAN-8、UPC-A、ITF-14、Code 128、Code 39に対応し、小売用のチェックデジットを計算します。間違った番号や桁の足りない番号は、黙って埋めて別の商品の有効なバーコードにしてしまうのではなく、拒否します。