Dev Study
← コードの外の約束 — 個人情報・ライセンス・生成物の権利
レッスン 3 / 10·約 9 分·第23期 コードの外の約束

ハッシュにしても、まだ誰かを指している

リクエストがアプリケーションに届くまで
  1. ブラウザURL入力
  2. DNS名前→IP
  3. ルータ経路選択
  4. ロードバランサ振り分け
  5. Nginx受け口
  6. アプリ処理今ここ
  7. DB保存

義務はデータそのものではなく、それで何をしたかに付いてきます。今回は、値をハッシュにして残す・束ねるという行為を見ます。

まず結論

ハッシュは一方向ですが、元の値の候補が少なければ全部試して戻せます。候補が多くて戻せなくても、同じ値は同じハッシュになるので、同じ人の行を束ねられます。GDPR は仮名化(pseudonymisation)したデータを匿名の情報とは分けて書いています。

本回は一次ソースが何を書いているかの紹介で、個別の事案の適否は判断しません。

? 読む前に予測

090 で始まる11桁の電話番号を SHA-256 にした値があります。Apple M4 の Mac で Node v24.21.0 の単一スレッドから、090 に続く8桁の全候補を順に試しました。全部試し終えるまでにかかった時間はどれでしょうか。

当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。

抽象原理

一方向でも、戻るかどうかは候補の数で決まる

第4期『なぜハッシュは戻せないのか』で、「ハッシュ関数を使ったから安全」では足りない、総当たりが速く回せればオフラインで試し尽くされる、と見ました。同じ性質は個人に関する値にも当てはまります。

ハッシュは出力から入力を計算で求められません。ただし、入力の候補を全部ハッシュにして見比べることはできます。戻るかどうかは関数の強さより、候補の数で決まります。

もう1つの性質があります。同じ入力は、いつ誰が計算しても同じ出力になります。だから元の値が分からなくても、同じハッシュの行は同じ値から来た行だと分かります。

ハッシュにした値に残る2つの性質
元の値電話番号・セッションIDなど
SHA-256
ハッシュ値出力から入力は計算できない
それでも残るもの
候補が少ないと戻る全候補をハッシュにして見比べる
同じ値は同じハッシュ戻らなくても行を束ねられる
  • ・左は候補空間の問題、右は決定性の問題で、別々に効く
  • ・どちらも SHA-256 の逆算の難しさとは別に効く
具体実物

電話番号の SHA-256 を、全候補で試す

架空の番号 09000004321(中の4桁を 0000 にした作例)を SHA-256 にし、090 に続く8桁を 00000000 から順にハッシュにして比べました。Apple M4、macOS 26.5.2、Node v24.21.0、単一スレッドの node:crypto です。2回実行した生出力です(# の行は追記した区切り)。

$ node l3-phone.mjs 09000004321(2回。# の行は追記)コマンド出力
# 1回目
target sha256: 2b70454ddf2f0b3ad1a81a49c9a00aaeb9d37753a759087ddb283680872fe086
candidates 100000000 total_sec 35.79 rate/s 2794040 found 09000004321 found_at_sec 0.00
# 2回目
target sha256: 2b70454ddf2f0b3ad1a81a49c9a00aaeb9d37753a759087ddb283680872fe086
candidates 100000000 total_sec 36.06 rate/s 2773012 found 09000004321 found_at_sec 0.00

1億候補を試し終えるまで約36秒。この番号は候補の前の方にあるので、見つかったのは開始直後でした。

逆算はしていません。1億通りしかないから全部試せた、それだけです。速度は単一スレッドの Node での値で、他の道具では測っていません。

✓ ここまでの確認

電話番号の SHA-256 が約36秒の総当たりで元に戻った、主な理由はどれですか。

抽象原理

戻らなくても、個人に結び付けられる

では候補が多くて戻らないなら、もう誰も指していないのでしょうか。GDPR は仮名化(pseudonymisation)を次のように定義します(第4条第5項、2016年官報版)。

‘pseudonymisation’ means the processing of personal data in such a manner that the personal data can no longer be attributed to a specific data subject without the use of additional information, provided that such additional information is kept separately and is subject to technical and organisational measures to ensure that the personal data are not attributed to an identified or identifiable natural person;

定義の後半は、追加情報を分けて保管し、管理の下に置くことまで含みます。「ハッシュにしたら仮名化」とは書かれていません。前文26 はその扱いを書きます。

Personal data which have undergone pseudonymisation, which could be attributed to a natural person by the use of additional information should be considered to be information on an identifiable natural person.

追加情報を使えば人に結び付けられるものは、識別されうる人の情報とみなすべきだ、と書いています。同じ前文は、識別できるかの判断に the costs of and the amount of time required for identification を考慮せよとし、手段の例に singling out(1人を選り分けること)を挙げます。データ保護の原則が及ばないのは anonymous information のほうです。

日本の個人情報保護法(2026-07-17 施行版。第2条第5・6項は、確認した最後の未施行版 2028-12-23 施行まで同文)にも2つの類型があります。

個人情報保護法 第2条(逐語から抜粋)表
第5項 仮名加工情報 他の情報と照合しない限り特定の個人を識別することができないように
個人情報を加工して得られる個人に関する情報
第6項 匿名加工情報 特定の個人を識別することができないように個人情報を加工して得られる
個人に関する情報であって、当該個人情報を復元することができないようにしたもの

仮名加工情報は「照合しない限り」識別できない、つまり照合すれば届く余地を残す類型です。匿名加工情報には「復元することができないようにした」が加わります。これは日本法の定義で、GDPR の2つの語と一対一で対応するとは原典は言っていません。加工の手順を定める第41条・第43条は 2028-07-16 施行の改正で変わります。

GDPR の個人データの定義には改正提案(COM(2025) 837、2025-11-19)があります。欧州議会の Legislative Train(2026-08-01 更新)では状態が Tabled で、成立していません。本回は 2016 年官報版で読みます。

具体実物

セッションIDのハッシュで、行を束ねる

32バイトの乱数で作ったセッションIDを SHA-256 にしてログに残します。候補は 2^256(約 1.158×10^77)通りで、総当たりでは戻りません。表示のためハッシュを先頭16桁に切ってあります(SHA-256 の出力は64桁です)。

$ node l3-session.mjs(1回目)コマンド出力
{"t":"10:00:01","sid_hash":"f09d6eb57bb112c9","path":"/login"}
{"t":"10:00:05","sid_hash":"d4990b67346171a8","path":"/login"}
{"t":"10:01:12","sid_hash":"f09d6eb57bb112c9","path":"/cart"}
{"t":"10:02:40","sid_hash":"f09d6eb57bb112c9","path":"/checkout"}
{"t":"10:03:02","sid_hash":"d4990b67346171a8","path":"/help"}
grouped by sid_hash: {"f09d6eb57bb112c9":["/login","/cart","/checkout"],"d4990b67346171a8":["/login","/help"]}
sid length (base64url chars): 43 => 256-bit random, candidates 2^256

元のIDは分からないのに、ログインから購入手続きまでの流れが1本に束ねられました。乱数なので2回目はハッシュ値が変わりますが、3行と2行に束ねられる形は同じでした。

OWASP Logging Cheat Sheet はまさにこれを勧めています。

Session identification values (consider replacing with a hashed value if needed to track session specific events)

追跡したいからハッシュにする。束ねられることが目的です。ハッシュは保護の手段として正しく使われていますが、束ねた行は1人の行動の記録として残ります。

✓ ここまでの確認

32バイトの乱数のセッションIDを SHA-256 にしてログに残しました。本文の実演から言えることはどれですか。

⇄ 2つを見比べる
具体例 A

電話番号の SHA-256

候補は090に続く8桁の1億通り。全部をハッシュにして見比べ、約36秒で全候補を試し、元の番号に戻った。関数は逆算していない。

何が効いたか表
候補の数 10^8(1億)
戻せたか 戻せた(全候補で約36秒)
行を束ねられるか 束ねられる
具体例 B

セッションIDの SHA-256

候補は2^256通りで総当たりでは戻らない。それでも同じIDの行は同じハッシュになり、1人の流れが1本に束ねられた。

何が効いたか表
候補の数 2^256(約1.158×10^77)
戻せたか 戻せない
行を束ねられるか 束ねられる

片方は戻り、片方は戻りません。それでも両方に共通して残っているものは何でしょうか。

3行目を見比べてください。

ここから先は法務へ

(a) エンジニアが気づける信号

  • 電話番号・会員番号のように、桁数や一覧が決まった値をハッシュにしている
  • ハッシュ列を結合や集計のキーに使っている、または社外へ送っている
  • 設計書や PR に「ハッシュにしたので個人情報ではない」と書かれている

(b) 法務に持っていく材料

  • 元の値の種類と候補の数の見積もり、ハッシュの方式(ソルトや鍵の有無)
  • 元の値の一覧や対応表を、どこで誰が持っているか
  • ハッシュ列で何と何を束ねているか、どこへ送っているか

(c) この回が言っていないこと

  • ハッシュにしたデータが個人情報に当たるか、仮名加工情報・匿名加工情報に当たるか
  • GDPR が自社に適用されるか
  • ソルトや鍵付きのハッシュにすれば、何が変わり何が残るか

この章のまとめ

  • ハッシュが戻るかは 候補の数 で決まる。090 に続く8桁の1億通りは、この Mac で約36秒だった。
  • 戻らなくても 同じ値は同じハッシュ。セッションIDのハッシュで1人の流れが束ねられ、OWASP はそれを追跡のために勧めている。
  • GDPR の pseudonymisation は 追加情報の分離と管理 まで含む定義で、前文26 は仮名化データと匿名の情報を分けて書く。
  • 個人情報保護法の仮名加工情報・匿名加工情報は日本法の別の定義。差は「復元することができないようにした」の有無。
  • 「ハッシュなら安全」も「ハッシュは無意味」も言い過ぎ。2つの性質を分けて見る。

自分の現場で確かめる

読んだだけでは身につきません。手元の環境で実際に見てみてください。

理解度チェック

読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。

問題 1 / 3正解: 0

GDPR 第4条第5項の pseudonymisation の定義に、条件として書かれているものはどれですか。

用語集(3語)
仮名化 (pseudonymisation)
GDPR 第4条第5項の用語。追加情報を使わなければ特定の本人に結び付けられないように処理すること。追加情報の分離保管と技術的・組織的措置が定義に含まれる。
匿名の情報 (anonymous information)
GDPR 前文26 の語。識別された・識別されうる人に関しない情報、または本人を識別できなくした個人データ。データ保護の原則は適用されるべきでないとされる。
仮名加工情報・匿名加工情報
個人情報保護法 第2条第5項・第6項が定める加工の類型。GDPR の語と一対一で対応するとは原典は言っていない。