このページで扱う主要キーワード(クリックで該当セクションへ):
「暗号化」 (Encryption / Cryptography) は、 SSDSE-B-2026 などの公的統計データを使った教材・分析で頻出するキーワードです。 本ページでは、 まず直感、 次に数式、 そして 47 都道府県の実値で確かめる、 という流れで体系的に整理します。 加えて、 ケーススタディ・FAQ・歴史的経緯・参考文献までを 1 ページに集約し、 用語の「地図」として使えるようにしました。
関連用語(前提・並列・発展)と関連グループ教材も末尾にまとめてあるので、 用語の地図として活用してください。
暗号化はデータを 意味不明な形(暗号文)に変換し、 鍵(key) を持つ者だけが復号できるようにする技術。 データサイエンスでは個人情報を扱う場面が頻発するため、 暗号化と関連概念(ハッシュ、 匿名化、 差分プライバシー)は必修です。
大別すると 2 方式:
実運用では ハイブリッド方式が主流。 公開鍵で「セッション鍵(共通鍵)」を安全に渡し、 大容量データはセッション鍵(AES)で暗号化します。 HTTPS / TLS はまさにこの構成。
共通鍵暗号は概念的に:
$M$=平文、 $C$=暗号文、 $K$=鍵、 $E,D$=暗号化/復号アルゴリズム。
公開鍵暗号(RSA の簡略):
$(e,n)$ は公開鍵、 $d$ は秘密鍵。 $n = pq$(大きな素数 2 つの積)の素因数分解が困難であることに安全性が基づく。
SHA-256 などはパスワード保管・改ざん検知に使う。 一方向性が要件。
| 用語 | 意味 | 例 |
|---|---|---|
| 平文 | 暗号化前のメッセージ | 「住所=東京都...」 |
| 暗号文 | 変換後のデータ | 「3f8a9c...」 |
| 鍵 | 暗号化/復号に必要な秘密の文字列 | AES-256 は 256 ビット |
| 共通鍵 (対称) | 暗号化と復号で同じ鍵 | AES、 ChaCha20 |
| 公開鍵 (非対称) | 異なる 2 つの鍵 (公開鍵 + 秘密鍵) | RSA、 ECC、 Ed25519 |
| ハッシュ | 固定長への一方向変換 | SHA-256、 SHA-3 |
| 電子署名 | 送信者を保証する仕組み | 秘密鍵で署名 → 公開鍵で検証 |
| 鍵管理 (KMS) | 鍵をどう生成・保管・廃棄するか | AWS KMS、 HSM |
| 匿名化 | 個人を特定不能にする処理 | k-匿名化、 差分プライバシー |
SSDSE-B-2026 そのものは 47 都道府県集計値で個人情報は含まれませんが、 仮にここに「個人レベルの住民データ」を結合する想定で安全策を考えます。
Fernet (AES-128-CBC + HMAC) で暗号化。 復号には Master Key が必要。パスワード保管の典型構成:
bcrypt $2b$12$... のような文字列だけ保存from cryptography.fernet import Fernet
key = Fernet.generate_key()
f = Fernet(key)
plaintext = b'patient_id=12345 | bp=130/85'
token = f.encrypt(plaintext)
print('暗号文:', token)
print('復号:', f.decrypt(token))
import pandas as pd
from cryptography.fernet import Fernet
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='shift_jis')
df.columns = df.iloc[0]
df = df.iloc[1:].reset_index(drop=True)
key = Fernet.generate_key()
f = Fernet(key)
# 仮の「個人ID」列を追加して暗号化(モデル用)
df['encrypted_id'] = df['地域コード'].apply(lambda s: f.encrypt(str(s).encode()).decode())
print(df[['都道府県','encrypted_id']].head())
import hashlib
with open('data/raw/SSDSE-B-2026.csv', 'rb') as fp:
digest = hashlib.sha256(fp.read()).hexdigest()
print('CSV の SHA-256:', digest)
# このダイジェストを別途記録しておけば、 ファイルが書き換えられたら検出できる
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes, serialization
priv = rsa.generate_private_key(public_exponent=65537, key_size=2048)
pub = priv.public_key()
msg = b'SSDSE-B-2026 集計結果 2026-05-20'
sig = priv.sign(
msg,
padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH),
hashes.SHA256())
print('署名長:', len(sig))
# 検証
pub.verify(sig, msg,
padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH),
hashes.SHA256())
print('検証 OK')
import bcrypt
pw = b'mySecretP@ss123'
hashed = bcrypt.hashpw(pw, bcrypt.gensalt(rounds=12))
print(hashed)
print('一致?:', bcrypt.checkpw(pw, hashed))
| レベル | 方式 | 安全性 |
|---|---|---|
| 1 | 平文保存 | 論外 |
| 2 | MD5 / SHA1 のみ | レインボーテーブルで一斉復元 → 危険 |
| 3 | 塩 + SHA-256 | 個別解読は必要だが GPU で高速 |
| 4 | bcrypt / scrypt / Argon2 | 計算コスト調整可、 推奨 |
import pandas as pd
from cryptography.fernet import Fernet
# 1) マスター鍵を環境変数から(コード/DB には書かない)
import os
key = os.environ['DATA_KEY'].encode()
f = Fernet(key)
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='shift_jis')
df.columns = df.iloc[0]
df = df.iloc[1:].reset_index(drop=True)
# 2) 識別子列を暗号化して保存
df['ID_enc'] = df['地域コード'].apply(lambda s: f.encrypt(str(s).encode()).decode())
df.drop(columns=['地域コード']).to_parquet('processed/secured.parquet')
「ヘッダ.ペイロード.署名」の 3 つを base64 で連結。 署名は HMAC-SHA256 または RSA。 認証 API で頻出。
import numpy as np
def dp_count(true_count, eps=1.0):
# Laplace ノイズで count をぼかす(教育用、 実運用は専用ライブラリ)
return true_count + np.random.default_rng().laplace(0, 1/eps)
# 例: 「東京都の高齢者数」を ε=1 でぼかす
print(dp_count(3_758_000, eps=1.0))
2024 年に NIST が標準化した次世代アルゴリズム:
RSA・ECC は量子計算機の Shor アルゴリズムで破られるため、 中長期で PQC への移行が進む。
ステップ 1:脅威モデルを決める
ステップ 2:鍵を作って環境変数へ
from cryptography.fernet import Fernet
key = Fernet.generate_key()
# .env に書き込む(リポジトリには絶対にコミットしない)
with open('.env', 'w') as f:
f.write(f'DATA_KEY={key.decode()}\n')
ステップ 3:列暗号化
import os, pandas as pd
from dotenv import load_dotenv
from cryptography.fernet import Fernet
load_dotenv()
f = Fernet(os.environ['DATA_KEY'].encode())
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='shift_jis')
df.columns = df.iloc[0]
df = df.iloc[1:].reset_index(drop=True)
# 仮の個人 ID 列を生成(実運用では実 ID)
df['person_id'] = 'P' + (df.index+1).astype(str).str.zfill(5)
df['person_id_enc'] = df['person_id'].apply(lambda s: f.encrypt(s.encode()).decode())
df.drop(columns=['person_id']).to_parquet('processed/secured.parquet')
ステップ 4:ハッシュ化(一方向)
import hashlib
def hsh(s, salt='SSDSE_2026'):
return hashlib.sha256((salt+s).encode()).hexdigest()
df['person_id_hash'] = df['person_id'].apply(hsh)
# DB の結合キーには hash を使う
ステップ 5:CSV のチェックサム
with open('data/raw/SSDSE-B-2026.csv','rb') as f_:
digest = hashlib.sha256(f_.read()).hexdigest()
print('CSV SHA-256:', digest)
# このダイジェストを版管理に記録 → 改ざんを検知
ステップ 6:通信暗号化(TLS)
外部に送るときは HTTPS 必須。 Python の requests はデフォルトで TLS 検証を行う。 自前 API なら Let's Encrypt の証明書で TLS 1.3 を立てる。
Web 通信の暗号化。 公開鍵で鍵交換 → 共通鍵で大容量データ。 ブラウザの鍵マークの背後。
bcrypt / Argon2 + 塩。 漏洩 DB でも個別パスワードを守る。 標準実装は passlib。
Transparent Data Encryption (TDE)、 列暗号化、 Always Encrypted。 個人情報列を選択的に保護。
JWT、 PDF 電子署名、 マイナンバーカード。 「本人が出した」を暗号で証明。
ハッシュチェーン + 公開鍵署名で改ざん不能な台帳。 暗号通貨・NFT・サプライチェーン追跡。
「データは送らず、 モデル更新だけ送る」。 暗号化通信 + 差分プライバシーで医療・金融データの連携学習。
「暗号化したまま計算する」最先端技術。 クラウドに復号鍵を渡さずに分析。
IC チップ内の秘密鍵で電子署名。 行政手続きのデジタル化の基盤技術。
openssl s_client で確認せよ。| アルゴリズム | 種類 | 鍵長 (推奨) | 用途 |
|---|---|---|---|
| AES | 共通鍵 (ブロック) | 128 / 192 / 256 | 大容量データ |
| ChaCha20 | 共通鍵 (ストリーム) | 256 | モバイル・TLS 1.3 |
| RSA | 公開鍵 | 2048 / 3072 | 鍵交換・署名 |
| ECC (P-256) | 公開鍵 | 256 | 軽量署名・TLS |
| Ed25519 | 公開鍵 | 256 | SSH・JWT |
| SHA-256 / 384 / 512 | ハッシュ | — | 改ざん検知・パスワード |
| SHA-3 | ハッシュ | — | 次世代標準 |
| bcrypt / Argon2 | パスワードハッシュ | — | パスワード保管 |
| ML-KEM (PQC) | 公開鍵 / KEM | — | 量子耐性鍵交換 |
| ML-DSA (PQC) | 公開鍵 / 署名 | — | 量子耐性署名 |
| 用語 | 意味 |
|---|---|
| 平文 | 暗号化前のデータ |
| 暗号文 | 暗号化後のデータ |
| 鍵 | 暗号化・復号に必要な秘密値 |
| 共通鍵 | 対称鍵。 AES, ChaCha20 |
| 公開鍵 | 非対称鍵。 RSA, ECC |
| 秘密鍵 | 公開鍵に対応する秘密値 |
| ハッシュ | 一方向関数。 SHA-256 |
| 塩 (salt) | ハッシュの逆引き対策 |
| IV | 初期化ベクトル |
| ナンス | 一度しか使わない値 |
| KMS | 鍵管理サービス |
| HSM | ハードウェアセキュリティモジュール |
| レシピ | コード |
|---|---|
| Fernet 鍵生成 | from cryptography.fernet import Fernet key = Fernet.generate_key() |
| Fernet 暗号化 | f = Fernet(key); ct = f.encrypt(b'secret') |
| Fernet 復号 | pt = f.decrypt(ct) |
| SHA-256 | import hashlib; hashlib.sha256(b'hello').hexdigest() |
| SHA-256 ファイル | with open('a.csv','rb') as f: hashlib.sha256(f.read()).hexdigest() |
| bcrypt パスワード | import bcrypt; h = bcrypt.hashpw(b'pw', bcrypt.gensalt(12)) |
| bcrypt 認証 | bcrypt.checkpw(b'pw', h) |
| RSA 鍵生成 | from cryptography.hazmat.primitives.asymmetric import rsa priv = rsa.generate_private_key(65537, 2048) |
| RSA 署名 | sig = priv.sign(msg, padding.PSS(...), hashes.SHA256()) |
| RSA 検証 | priv.public_key().verify(sig, msg, padding.PSS(...), hashes.SHA256()) |
| AES-GCM | from cryptography.hazmat.primitives.ciphers.aead import AESGCM aesgcm = AESGCM(key); ct = aesgcm.encrypt(nonce, pt, aad) |
| HMAC | import hmac, hashlib; h = hmac.new(key, msg, hashlib.sha256).hexdigest() |
| 塩 (salt) 生成 | import secrets; salt = secrets.token_bytes(16) |
| セキュア乱数 | secrets.token_urlsafe(32) |
| Argon2 | from argon2 import PasswordHasher
ph = PasswordHasher(); hash_ = ph.hash('pw') |
歴史と位置づけ:暗号の歴史は古代ローマのシーザー暗号にまで遡りますが、 数学的体系化は 20 世紀。 主要な節目:
データサイエンスとの接点は、 (1) 個人情報を扱う前提技術として、 (2) プライバシー保護機械学習(連合学習・同型暗号・差分プライバシー)、 (3) ブロックチェーン上の改ざん不能データ、 の 3 方向に広がっています。
暗号関連技術の俯瞰:
[暗号化]
│
┌────────────┼────────────┐
共通鍵 公開鍵 ハッシュ
(AES) (RSA, ECC) (SHA-256, bcrypt)
│ │ │
▼ ▼ ▼
大容量暗号 鍵交換・署名 改ざん検知・パスワード保管
│ │ │
└────► TLS / HTTPS ◄──────────┘
│
匿名化 / 差分プライバシー / 同型暗号
(暗号化+プライバシー保護)