このページの主要な見どころ。 気になる項目から読み始めてください。
電子署名 = メッセージのハッシュを送信者の秘密鍵で暗号化したもの。 受信者は公開鍵で復号し、 本文のハッシュと一致するかを検証する。
論文・実務レポート・公的統計の解説で、 こんな場面に出会ったはずです。
この「ハッシュ + 公開鍵で本人性を担保する」発想が電子署名の核です。 本ページでは SSDSE-B-2026.csv を実例として、 署名生成・検証・改ざん検出を Python で実装します。 配布元としても受信者としても、 数学的に「途中で誰かが書き換えていない」と確信できる仕組みを身につけられます。
「封蝋 (sealing wax) のデジタル版」です。 中世の手紙では書いた人だけが持つ印章を蝋に押し付け、 ① 「本人が書いた」、 ② 「開封されていない」 を示しました。 電子署名は同じ役割をデジタルで担います。
身近なアナロジー:
暗号化との対比 (超重要):
| 場面 | 使う鍵 | 目的 |
|---|---|---|
| 暗号化(送る側) | 受信者の公開鍵 | 受信者しか復号できない(秘密性) |
| 復号(受ける側) | 受信者の秘密鍵 | 中身を読む |
| 署名(送る側) | 送信者の秘密鍵 | 本人にしか作れない印 |
| 検証(受ける側) | 送信者の公開鍵 | 本人が作ったか確認 |
暗号化は「受信者の鍵ペア」、 署名は「送信者の鍵ペア」と覚えてください。 鍵の方向が逆という点が初学者が必ずつまずくポイントです。
3 つの保証を分解: 本人性 (誰がそれを送ったか)、 完全性 (改ざんされていないか)、 否認防止 (送ったことを後から否定できない)。 これら 3 つを 1 つの仕組みで同時に満たすため、 電子契約・電子納税・ブロックチェーンの全てが電子署名に依存します。
SSDSE のような公的統計データでも、 署名付きで配布されると「これは確かに統計局が作ったものですよ」「途中で誰かが書き換えていませんよ」と数学的に保証できます。 1 ビット書き換えればハッシュは全く別物になる「雪崩効果」のおかげです。 これがあるからこそ、 研究者はネットワーク経由で受け取った CSV を疑わずに分析を始められます。
電子署名と紙の判子の違い:紙の印鑑は同じ印影を何度押しても同じになりますが、 電子署名は対象データが変われば全く別の値になります。 これにより「この署名はこの文書専用」になり、 他文書への流用が物理的に不可能になります。
処理の流れ図 (ASCII):
[送信者]
m (SSDSE-B-2026.csv)
│
├─ H(m) = SHA-256 ハッシュ
│
├─ Sign(sk, H(m)) = σ (署名値)
│
└─ 送る: {{m, σ, 公開鍵証明書}}
│
▼
[受信者]
① 証明書を CA で検証
② H(m) を再計算
③ Verify(pk, m, σ) == 1 か確認
└─ OK → 信頼して分析開始
└─ NG → 改ざん or 鍵不正
電子署名スキームは 3 つのアルゴリズム の組 $(\mathsf{KeyGen}, \mathsf{Sign}, \mathsf{Verify})$ で定義されます。
① 鍵生成:
$\lambda$ はセキュリティパラメータ(鍵長)。 $pk$ は公開鍵、 $sk$ は秘密鍵。
② 署名生成:
$m$ はメッセージ、 $H(\cdot)$ は SHA-256 などの暗号学的ハッシュ関数、 $\sigma$ は署名値。
③ 検証:
RSA 署名の具体例:
$N = pq$ は大きな合成数、 $(e, N)$ が公開鍵、 $d$ が秘密鍵で $ed \equiv 1 \pmod{\phi(N)}$。
ECDSA (楕円曲線署名):
$G$ は曲線の基点、 $d$ は秘密鍵、 $k$ は使い捨て乱数。 $(r, s)$ が署名値。
EdDSA (Ed25519):
決定的に $r$ を生成する。 サイドチャネル攻撃に強い。
セキュリティ要件 (EUF-CMA):
適応的選択メッセージ攻撃下で、 鍵を持たない攻撃者が新しい署名 $(m^*, \sigma^*)$ を偽造できる確率は無視できる。
ハッシュ関数の必要性質:
SHA-256 はいずれも満たしますが、 MD5・SHA-1 は ③ が破られているため電子署名には使えません。
| 記号 | 読み方 | 意味・例 |
|---|---|---|
| $m$ | message | 署名対象データ。 SSDSE-B-2026.csv の全バイト列 |
| $H(m)$ | hash | SHA-256 等で得られる 256 bit の指紋 |
| $sk, pk$ | secret/public key | $sk$ は本人だけが保管、 $pk$ は配布可 |
| $\sigma$ | signature | 署名値。 RSA-2048 なら 256 bytes |
| $N, e, d$ | RSA modulus / public / private exp. | $(e, N)$ を公開、 $d$ は厳重保管 |
| $\phi(N)$ | Euler's totient | $\phi(pq) = (p-1)(q-1)$ |
| $G, n$ | 基点 / 位数 | 楕円曲線の点とその位数。 secp256r1 など |
| $k$ | nonce | 署名ごとに新しく取る乱数。 再利用厳禁 |
| $\ell$ | order (EdDSA) | 群の位数 |
| $\mathsf{negl}(\lambda)$ | negligible | $\lambda$ について多項式逆数より速く 0 へ |
数式の核心は 「秘密鍵でしか作れない値だが、 公開鍵で誰でも検証できる」 という非対称性です。 これが本人性と否認防止を支える数学的根拠です。
$\sigma^e \equiv H(m) \pmod N$ という式は、 RSA の世界で「秘密鍵 $d$ で作った署名は、 公開鍵 $e$ で戻すと元のハッシュに戻る」という関係を表しています。 もし $\sigma$ を秘密鍵なしに作ろうとすると、 大きな数 $N$ を素因数分解する必要があり、 2048 bit RSA であれば現実時間では不可能です。
同様に ECDSA では、 楕円曲線上の離散対数問題が困難であることを安全性の根拠としています。 ECDSA の方が鍵長が短いのに同等の安全性を持つため、 モバイル・IoT で広く使われます。
"確率 $\mathsf{negl}(\lambda)$" という表現は暗号理論で頻出します。 これは「鍵長を増やせば、 攻撃成功確率は急速に 0 に近づく」ことを意味し、 セキュリティパラメータ $\lambda$ を大きくすれば計算量上現実的に破られない、 という保証になります。
署名検証の数式を「言葉」で読むと:
もし攻撃者が $m$ を改ざんしたら、 ステップ 1 で計算するハッシュが変わり、 ステップ 3 で不一致になる。 もし攻撃者が $\sigma$ を改ざんしたら、 ステップ 2 の結果がランダムになり、 やはり不一致になる。 だから両方守られます。
SSDSE-B-2026 を配布する立場で、 ファイルが配布途中で改ざんされていないことを保証するシナリオを考えます。
RSA-1024 の小さな手計算例 ($p=61, q=53$):
$N = 61 \times 53 = 3233$, $\phi(N) = 60 \times 52 = 3120$, 公開指数 $e = 17$, 秘密指数 $d = 2753$ (拡張ユークリッドより)。
仮にハッシュ値が $H(m) = 123$ だったとすると:
検証側は $\sigma^{e} = 855^{17} \bmod 3233 = 123$ を計算し、 これがハッシュと一致するので OK。
| ファイル | 想定 SHA-256 (例) | 検証結果 |
|---|---|---|
| SSDSE-B-2026.csv (正規) | 4f3a...c12e | ✅ 一致 → 改ざんなし |
| SSDSE-B-2026.csv (北海道人口 +1) | 9b71...8e02 | ❌ 不一致 → 改ざん検出 |
| SSDSE-B-2026.csv (BOM 追加のみ) | 2c44...11ab | ❌ 不一致 (BOM もデータ) |
| SSDSE-B-2026.csv (改行を CRLF→LF) | 87bc...4f29 | ❌ 不一致 (改行もバイト) |
「1 ビット変えてもハッシュは大幅に変わる」性質を 雪崩効果 (avalanche effect) と呼びます。
| 鍵長 / アルゴリズム | 想定セキュリティ | 署名サイズ | 署名速度 (1 ファイル) | 用途 |
|---|---|---|---|---|
| RSA-2048 | 112 bit 相当 | 256 B | ~5 ms | TLS 証明書・電子契約 |
| RSA-3072 | 128 bit 相当 | 384 B | ~15 ms | 長期保管 |
| RSA-4096 | 140 bit 相当 | 512 B | ~40 ms | 政府機関の長期署名 |
| ECDSA-P256 | 128 bit 相当 | ~72 B | ~1 ms | モバイル・IoT |
| EdDSA (Ed25519) | 128 bit 相当 | 64 B | ~0.5 ms | SSH / Tor |
| Dilithium2 | ポスト量子 NIST L2 | 2.4 KB | ~3 ms | 長期 (量子計算機対策) |
SSDSE-B-2026 は数 MB のファイルなので、 SHA-256 計算は 100 ms 以下、 署名生成も 10 ms 以下で済みます。 通信オーバヘッドは無視できる軽さです。
SSDSE-B-2026 の都道府県別 「行ハッシュ」 でデータ品質保証する例:47 都道府県 × 約 30 年 = 約 1,400 行に対して、 各行をシリアライズしてハッシュ化すれば、 「どの都道府県のどの年度が書き換わったか」 まで特定できます。 配布時に row_fingerprint.csv を添付しておくと、 監査時にとても便利です。
① SHA-256 ハッシュを計算
import hashlib
with open('data/raw/SSDSE-B-2026.csv', 'rb') as f:
raw_bytes = f.read()
digest = hashlib.sha256(raw_bytes).hexdigest()
print('SHA-256:', digest)
print('ファイルサイズ:', len(raw_bytes), 'bytes')
# 1 文字変えるだけで雪崩効果でハッシュは全く別物に
tampered = raw_bytes.replace(b'\xe5\x8c\x97\xe6\xb5\xb7\xe9\x81\x93',
b'\xe5\x8c\x97\xe6\xb5\xb7\xe9\x81\x95')
print('tampered:', hashlib.sha256(tampered).hexdigest())② 鍵ペアの生成 (RSA-2048)
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes, serialization
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
public_key = private_key.public_key()
with open('private.pem', 'wb') as f:
f.write(private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()))
with open('public.pem', 'wb') as f:
f.write(public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo))③ SSDSE-B-2026.csv に署名する
with open('data/raw/SSDSE-B-2026.csv', 'rb') as f:
message = f.read()
signature = private_key.sign(
message,
padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH),
hashes.SHA256()
)
with open('data/raw/SSDSE-B-2026.csv.sig', 'wb') as f:
f.write(signature)
print('署名長:', len(signature), 'bytes') # RSA-2048 なら 256 bytes④ 受信者側で検証する
from cryptography.exceptions import InvalidSignature
with open('public.pem', 'rb') as f:
pub = serialization.load_pem_public_key(f.read())
with open('data/raw/SSDSE-B-2026.csv', 'rb') as f:
received_msg = f.read()
with open('data/raw/SSDSE-B-2026.csv.sig', 'rb') as f:
received_sig = f.read()
try:
pub.verify(received_sig, received_msg,
padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH),
hashes.SHA256())
print('OK: 本物の SSDSE-B-2026 です')
except InvalidSignature:
print('NG: ファイルが改ざんされているか鍵が違います')⑤ SSDSE-B-2026 の都道府県別行ハッシュ
import pandas as pd, hashlib
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='utf-8', skiprows=1)
def row_fingerprint(row):
serial = '|'.join(str(v) for v in row.values)
return hashlib.sha256(serial.encode('utf-8')).hexdigest()[:16]
df['fingerprint'] = df.apply(row_fingerprint, axis=1)
print(df[['Prefecture','Year','fingerprint']].head(10))
# 後日同じ df を読み直してハッシュ比較すれば差分検知ができる
df[['Prefecture','Year','fingerprint']].to_csv(
'data/raw/SSDSE-B-2026.row_fingerprints.csv', index=False)⑥ ECDSA も併記
from cryptography.hazmat.primitives.asymmetric import ec
ec_priv = ec.generate_private_key(ec.SECP256R1())
ec_pub = ec_priv.public_key()
ec_sig = ec_priv.sign(message, ec.ECDSA(hashes.SHA256()))
print('ECDSA 署名長:', len(ec_sig), 'bytes')
ec_pub.verify(ec_sig, message, ec.ECDSA(hashes.SHA256()))
print('ECDSA 検証 OK')⑦ EdDSA (Ed25519) を使う
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
ed_priv = Ed25519PrivateKey.generate()
ed_pub = ed_priv.public_key()
ed_sig = ed_priv.sign(message)
print('Ed25519 署名長:', len(ed_sig), 'bytes') # 64
ed_pub.verify(ed_sig, message)
print('Ed25519 検証 OK')実世界で電子署名・データ分散処理などの概念がどう適用されているか、 代表的なケーススタディを紹介します。
ウェブブラウザの 🔒 マークは、 サーバ証明書を CA が署名し、 ブラウザがその署名を検証して「本物のドメインか」を判定している。
配布される実行ファイル・パッケージは開発者の秘密鍵で署名され、 OS/パッケージマネージャが検証してから実行する。 マルウェア混入を防ぐ。
すべての取引は送信者が秘密鍵で署名し、 受信者と承認ノードが公開鍵で検証する。 ECDSA / Schnorr / BLS が使われる。
紙の押印に代えて、 電子証明書 + タイムスタンプ署名で「いつ・誰が・何に同意したか」を証明する。 電子帳簿保存法・eIDAS で法的有効性。
本ページの題材。 配布元が署名 + ハッシュを公開、 受信者は検証して「正規の配布物だ」と確認できる。 研究の再現性のために重要。
Q. 紙のハンコと電子署名はどちらが強い?
A. 電子署名の方が圧倒的に強い。 紙の印鑑は複製が容易ですが、 電子署名は数学的に偽造不可能。 加えて時刻・対象データ・鍵主体の 3 点まで証明できる。
Q. 電子署名と HMAC の違いは?
A. 電子署名は 非対称鍵 なので否認防止が成立する。 HMAC は対称鍵で、 共有秘密を知る両者が同じ MAC を作れるため否認防止は無い。 API 認証など内部用途で HMAC、 公開配布で電子署名。
Q. 量子計算機が登場したらどうなる?
A. RSA・ECDSA・EdDSA はすべて Shor のアルゴリズムで破られる可能性がある。 NIST が 2024 年に Dilithium・SPHINCS+ を標準化。 長期保存が必要な署名は移行を計画。
Q. SSDSE のような公共データに毎回検証が必要?
A. 研究の再現性・データ ETHICS の観点から推奨。 特に分析結果を公開する場合は「使用したデータの正規性を確認した」と記録する。
Q. プログラムから署名するときの鍵管理ベストプラクティス
A. 本番では HSM (Hardware Security Module) または KMS (AWS KMS, GCP KMS, Azure Key Vault) を使う。 ローカル開発では暗号化されたキーストア。 git にコミットしない。