機密性 (Confidentiality) = 「許可された人だけが情報を読めること」。情報セキュリティの 3 大原則 CIA (Confidentiality / Integrity / Availability) のうち最初の C。
用語集 → セキュリティ → 機密性 (Confidentiality)。CIA (機密性・完全性・可用性) の C 担当。暗号化・アクセス管理 は機密性を実装する具体的手段。
データ解析の文脈では「公開していい統計量」と「個人が特定できる個票」を分け、後者を保護することが機密性の中心テーマです。SSDSE は既に集計済みのオープンデータですが、本ページではあえて「もし個票だったら?」を想像し、$k$-匿名化や差分プライバシーで都道府県粒度に粗化するシミュレーションを行います。
「机の上の書類に鍵をかける」のデジタル版。鍵をかける場所は 3 つあります:① 保存時 (at rest)、② 通信時 (in transit)、③ 利用時 (in use)。
| 場面 | 技術 | 例 |
|---|---|---|
| at rest (保存) | ディスク暗号化 / AES-256 / KMS | FileVault、BitLocker、S3 SSE |
| in transit (通信) | TLS 1.3 / VPN / mTLS | HTTPS、WireGuard |
| in use (利用) | TEE / 準同型暗号 / MPC | Intel SGX、AMD SEV |
| 統計データ | $k$-匿名化 / 差分プライバシー | SSDSE 集計、US Census |
機密性が破られる典型例: ① パスワードがメモ用紙に書いてある、② 公衆Wi-Fi で平文 HTTP を使う、③ ノート PC を電車に置き忘れる、④ アクセス権限が広すぎる、⑤ ログに個人情報を平文で書く、⑥ 集計テーブルから人物が特定できてしまう (差分攻撃)。
$k$-匿名性 (k-anonymity): データセット $D$ の任意のレコードが、識別子 (準識別子) で見ると少なくとも他の $k-1$ レコードと区別できないこと。
$$ \forall r \in D, \quad \left|\{ r' \in D \mid \mathrm{QI}(r) = \mathrm{QI}(r') \}\right| \ge k $$
$\mathrm{QI}$ は準識別子 (都道府県・年齢階級・性別など)。$k$ が大きいほどプライバシー保護が強い。
差分プライバシー ($\varepsilon$-DP):
$$ \Pr[\mathcal{M}(D) \in S] \le e^{\varepsilon} \cdot \Pr[\mathcal{M}(D') \in S] $$
$D, D'$ は 1 レコードだけ違う隣接データセット。$\varepsilon$ が小さいほど「1 人加わっても結果がほとんど変わらない」=機密性が高い。Apple, Google, US Census が採用。
ラプラスメカニズム:
$$ \mathcal{M}(D) = f(D) + \mathrm{Lap}\!\left( \frac{\Delta f}{\varepsilon} \right) $$
$\Delta f$ は感度 (1 件変化でクエリの値が動く最大値)。例: SSDSE で「人口」を返すクエリなら $\Delta f = 1$。
AES の安全性 (簡略):
$$ \Pr[\mathrm{distinguish}] \le \mathrm{negl}(\lambda), \quad \lambda \in \{128, 192, 256\} $$
鍵長 $\lambda$ ビットの AES は、現実的計算量では区別不可能。
| 記号 | 読み方 | 意味 |
|---|---|---|
| $D, D'$ | database | データセットと隣接データセット |
| $\mathrm{QI}$ | quasi-identifier | 単独では識別不能だが組合せで特定できる属性 |
| $k$ | k | 同一 QI を共有するレコード数の下限 |
| $\varepsilon$ | epsilon | 差分プライバシーの予算 (小さいほど強い) |
| $\Delta f$ | sensitivity | クエリの感度 (1 件変動の最大幅) |
| $\mathcal{M}$ | mechanism | ノイズを加えるなどのプライバシーメカニズム |
仮に「年齢別・職業別・都道府県別」の個票が存在したとして、ある住民が再特定されないために必要な粗化粒度を見積もります。
| 公表粒度 | 代表セル人数 (例) | k-匿名性 | 判定 |
|---|---|---|---|
| 都道府県 (47) | 数十万〜千万 | k≥10000 | 公表 OK |
| 市区町村 (1700) | 数百〜数十万 | k≥100 | 概ね OK |
| 郵便番号 7 桁 | 数〜数百 | k=1〜10 | 危険 |
| 住所 | 1〜数 | k=1 | 特定可能 |
→ SSDSE が都道府県粒度なのは、$k$-匿名性が十分高くなるための合理的な選択。
差分プライバシーの数値例:
| $\varepsilon$ | 解釈 | $\mathrm{Lap}(1/\varepsilon)$ の SD |
|---|---|---|
| 0.1 | 非常に強いプライバシー | 14.1 |
| 1.0 | バランス型 (推奨) | 1.41 |
| 10 | 弱い | 0.14 |
① SSDSE 読込と機密粒度の確認
import pandas as pd
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8', skiprows=1)
# 各セル (都道府県, 年度) は何人を代表しているか
size = df.groupby('Prefecture')['Total_population'].mean()
print('最小セルの人数:', size.min()) # 鳥取県 ≈ 55 万人 → k=55 万級
print('k-匿名性として十分: 都道府県集計は安全圏')
② AES-256 で SSDSE ファイルを暗号化保存
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os
key = AESGCM.generate_key(bit_length=256)
aes = AESGCM(key)
nonce = os.urandom(12)
with open('data/raw/SSDSE-B-2026.csv', 'rb') as f:
plaintext = f.read()
cipher = aes.encrypt(nonce, plaintext, associated_data=b'SSDSE-2026')
with open('data/raw/SSDSE-B-2026.csv.enc', 'wb') as f:
f.write(nonce + cipher)
# 復号
data = open('data/raw/SSDSE-B-2026.csv.enc','rb').read()
plain = aes.decrypt(data[:12], data[12:], b'SSDSE-2026')
assert plain == plaintext
③ $k$-匿名性の確認
def k_anonymity(df, quasi_id_cols):
counts = df.groupby(quasi_id_cols).size()
return counts.min(), counts.describe()
k_min, summary = k_anonymity(df, ['Prefecture', 'Year'])
print(f'最小グループサイズ k = {k_min}')
print(summary)
④ ラプラスメカニズムで差分プライバシー集計
import numpy as np
def dp_sum(values, epsilon=1.0, sensitivity=1.0):
noise = np.random.laplace(loc=0.0, scale=sensitivity / epsilon)
return values.sum() + noise
# 都道府県別の人口合計に DP ノイズを加えて公開
dp_pop = df.groupby('Prefecture')['Total_population'].apply(
lambda s: dp_sum(s, epsilon=1.0, sensitivity=1000))
print(dp_pop.head())
⑤ TLS で都道府県データを安全に送信 (HTTPS 例)
import requests
# TLS 1.3 の HTTPS 通信なら、 中身は中継ノードからは見えない
r = requests.get('https://www.stat.go.jp/data/ssdse/index.html',
verify=True, timeout=10)
print('証明書検証 OK:', r.status_code)
⑥ ログをマスキングして書き出す
import re, hashlib
def mask_email(s):
return re.sub(r'([\w.\-]+)@', lambda m: m.group(1)[:2] + '***@', s)
def hash_id(s):
return hashlib.sha256(s.encode()).hexdigest()[:12]
print(mask_email('analyst.taro@example.go.jp'))
print(hash_id('user_42_taro'))
情報セキュリティ (CIA) ├─ 機密性 (Confidentiality) ★ │ ├─ 暗号 (at rest / in transit / in use) │ ├─ アクセス制御 (RBAC / ABAC) │ ├─ プライバシー保護 (k-匿名 / DP / MPC) │ └─ 法令 (個情法 / GDPR / HIPAA) ├─ 完全性 (Integrity) └─ 可用性 (Availability) 機密性 ★ ├─ 攻撃面:盗聴 / 内部不正 / サイドチャネル └─ 対策:暗号化 / 認証 / マスキング / DLP