ちいつる
A-11リファレンス

暗号化・エンコーディングの実装

仕組みの解説と、機密データをローカル処理に留める設計思想をセットで扱う。

触ってみる文字を書き換えると、即座に変換結果も変わります
QVBJ44Kt44O844Gn44Gv44Gq44GP44CB44Gf44Gg44Gu5paH56ug

一瞬で行き来できてしまうのが答え。Base64は「隠す」仕組みではなく「運べる形に変える」仕組みでしかない。

Base64・URLエンコードの仕組み

Base64は「暗号化」ではなく「エンコード」であり、誰でも即座に元に戻せる。バイナリデータをテキストとして安全に運ぶための変換に過ぎず、機密情報の保護には使えない。URLエンコードも同様に、URLに使えない文字を安全な表記に変換するだけの処理である。この2つを「暗号化」だと誤解すると、意図せず機密情報を平文同然で扱ってしまう。

触ってみるスペースや記号・日本語を入れてみてください
a%20b&%26c=%3D%E3%81%82🎁%F0%9F%8E%81
エンコード結果
a%20b%26c%3D%E3%81%82%F0%9F%8E%81

5文字が %XX に置換されました。多バイト文字はUTF-8のバイト数だけ % が並びます。

%XX に化けた文字は、鍵で守られたのではなく「URLに載る形」に整えられただけ。多バイト文字がバイト数だけ % を並べるのも、中身がそのまま透けている証拠だ。

触ってみる文字を打ち、行をタップしてビットの目印を開いてみてください
先頭01000001

先頭が 0 で始まる1バイトは、そのままASCII。

3文字=合計8バイト。ASCIIは1バイト、日本語は3バイト、多くの絵文字は4バイト。バイト先頭の目印ビットが「ここから何バイトで1文字」を示すので、機械は文字数とバイト数のズレを取り違えずに戻せます。

1文字が何バイトになるかは、先頭バイトの目印ビットが決めている。この符号化があるから、Base64もURLエンコードも潰さずにきっちり元へ戻せる。潰して二度と戻さないハッシュとは、ここが根本から違う。

ハッシュ関数の基礎(用途と限界)

ハッシュ関数(SHA-256等)は、元のデータから一方向にしか変換できない値を作る。パスワードそのものではなくハッシュ値を保存する用途に使われるが、「よくあるパスワード」はハッシュ値から逆引きされるリスクがあるため、実務ではソルト(ランダムな追加値)を加えたうえで、ハッシュ計算に時間をかける専用アルゴリズム(bcrypt等)を使う。

触ってみるどちらかの入力を1文字だけ変えてみてください
0/256ビットが相違(0.0%)

1文字の違いでも全256ビットのおよそ半分が変わります(雪崩効果)。色付きが相違した16進文字。

たった1文字の違いで、ハッシュ値の半分近いビットが一斉に裏返る。これが「雪崩効果」。出力をいくら眺めても入力の手がかりが残らないから、元データへ逆算する道が断たれている。

触ってみるソルトのあり/なしを切り替えてみてください
ユーザーソルト保存されるハッシュ辞書照合
A さん(なし)
B さん(なし)

ソルトなしでは、パスワードが辞書に載っていればハッシュから即座に元の語が判明する。

一方向でも、「よくある語→ハッシュ」の対応表を先に作っておけば逆引きは通ってしまう。そこへソルトを一振り。表は丸ごと空振りになり、同じパスワードを使った二人ですら別々のハッシュに散らばる。

触ってみるコスト係数を上げて計算ボタンを押してください
反復回数(コスト係数)= 212 = 4,096
2^12
1回のパスワード検証

ボタンで実測します。正しい利用者は1回だけ待てばよいので、多少遅くても気になりません。

正規のログインは一回数十msで終わるので、重さには誰も気づかない。ところが総当たり側は試行のたびに同じ重さを食らい、反復回数のぶんだけ所要時間が倍々に膨らんでいく。わざと遅くする、それが bcrypt 等の発想。

パスワード生成のエントロピー設計

パスワードの強度は「文字種の多さ」と「長さ」の組み合わせで決まるエントロピー(情報量)で測れる。使用できる文字種の数をN、長さをLとすると、組み合わせ総数はN^Lで指数的に増える。12文字の英数記号混在なら、多くの攻撃手法に対して現実的な時間では破られない強度になる。

触ってみる長さと文字種を変えて、解読時間の変化を見てください
パスワードの長さ
8文字
組み合わせ = 368エントロピー 41.4 bit

毎秒100億回の総当たり攻撃を受けた場合、全探索に約5分かかる計算になります。

文字種をもう1種類足すより、長さを1文字伸ばすほうがゲージは大きく動く。組み合わせ数は N^L。効いてくるのは、底のNではなく指数側のLだからだ。

触ってみるNを決めて「5万回ふる」を押し、素朴な剰余と棄却サンプリングを見比べてください
作りたい範囲 N(1バイト乱数を 0〜9 に変換)
0〜9

256はN=10で割り切れず、余り6個が下位の目に上乗せされる。青い目は理論上 約4.0% 出やすく、「5万回ふる」を押すと実測でも青い目が公平ラインを超えていきます。

高いエントロピーを設計しても、乱数の作り方が雑だと台無しになる。素朴な剰余だと特定の目が数%多く出る(modulo bias)。余りの範囲を捨てる棄却サンプリングに替えれば、その偏りは消える。同じ乱数の流れでも、作り方ひとつで公平さがこれだけ変わる。

機密データをローカル処理する設計思想

JSON整形・パスワード生成のようなツールは、入力値を一切サーバーへ送らずブラウザ内だけで処理する設計にできる。「AIチャットにAPIキー入りのJSONを貼る」行為はその内容がサーバー・ログに残るリスクを伴うため、ローカル処理で完結するツールの方が機密データの扱いとして安全である。

触ってみる鍵と受信側の鍵を変えてみてください
暗号文(各バイトを鍵とXOR)
18 04 04 1b 0e 15 4a 1d 04 0a 02 07
secret-token

暗号化も復号も同じ鍵ひとつ。処理はこの画面(ブラウザ内)だけで完結し、平文も鍵もどこにも送信されません。鍵が1文字でも違えば結果は壊れます。

鍵があれば戻せる暗号化と、戻せないハッシュ。その線引きが手元で確かめられる。しかも暗号化も復号もこの画面の中だけで起き、平文も鍵も外へ一歩も出ていかない。

触ってみる送信/ローカルを切り替えて処理ボタンを押してください
📱端末
🖥️サーバー
サーバーログ / CDNキャッシュ(消えずに残る)

まだ何も記録されていません。

送信した瞬間、機密データはサーバーやログ・キャッシュに残り、あとから消すのは困難です。

一度送信した機密は、こちらが忘れてもログに残って積み上がっていく。かたやローカル処理は、何度押しても端末の外へ出ない。「AIチャットにAPIキーを貼る」危うさと、手元で完結するツールの安全性の差。それが、消えずに残るログの量となって現れる。

次はこれ