NET // communication networks
LESSON 39 / 発展編

ディジタル署名 ─ ハッシュ + 公開鍵の合わせ技

「このメッセージは確かにあなたが書いた」を、第三者が客観的に検証できる形にしたものが ディジタル署名。共有鍵の MAC では「2 者のうちどちらが書いたか」を判別できませんが、署名なら 秘密鍵を持つ署名者しか作れない ので、否認防止が成立します。本講では ハッシュ関数と公開鍵暗号の合わせ技 として署名の仕組みを整理し、RSA-PSS、ECDSA、Ed25519 の主要方式、X.509 証明書、コードサイニング、Git コミット署名、PQC 署名(Dilithium・SPHINCS+) までを扱います。

学習目標

本講を終えると、以下を達成できるようになります。

本講は 第38回 ハッシュ関数・MAC第37回 公開鍵暗号 の両方を前提とします。署名は 「ハッシュで圧縮 + 公開鍵で署名・検証」 という合わせ技なので、両方を理解していないと中身が分かりません。続く 第25回 TLS と PKI で扱う X.509 証明書も、本講で見るとより腹落ちします。

このレッスンの目次

01 ディジタル署名とは MAC との違い、提供する 4 つの性質… 02 ハッシュ + 公開鍵 標準的な署名スキームの仕組み… 03 主要アルゴリズム RSA-PSS / ECDSA / Ed25519 の使い分け… 04 X.509 証明書 CA 階層と署名の連鎖… 05 コードサイニング アプリ・ドライバ・パッケージの署名… 06 OpenSSL ハンズオン openssl dgst -sign / -verify を回す… 07 PQC 署名 Dilithium と SPHINCS+ ─ 量子時代の署名… 08 まとめと用語 本講の重要語句を整理 09 確認問題 5 問で理解度をチェック

ディジタル署名とは ─ MAC との決定的な違い

ディジタル署名は 「秘密鍵で文書に印を付け、公開鍵を持つ誰もがその印を検証できる」 仕組み。MAC が「2 者間の認証(共有鍵)」だったのに対し、署名は 「1 対多の認証」「客観的検証」「否認防止」 を成立させます。
POINT ディジタル署名が提供する 3 つの性質:
1. 完全性(Integrity) ─ 署名後にメッセージが改ざんされたら検証失敗
2. 認証(Authentication) ─ 公開鍵に紐づく署名者本人が作成したと確認できる
3. 否認防止(Non-repudiation) ─ 署名者は「自分が作ったものではない」と否認できない

暗号化(機密性)は別。署名は中身を隠さず、改ざんと作成者を保証する。

MAC vs ディジタル署名 ─ 改めて整理

性質MAC(第38回)ディジタル署名(本講)
共有秘密鍵 1 つ秘密鍵 + 公開鍵
署名共有鍵で計算秘密鍵で計算
検証共有鍵で計算し直す公開鍵で計算
検証可能な相手共有鍵を持つ人だけ公開鍵を知っている誰でも
否認防止不可能可能(法的有効性あり)
速度非常に高速遅い(公開鍵演算が重い)
用途API 認証、TLS 内部、Webhook 検証証明書、ソフトウェア配布、契約書

なぜ「否認防止」が成立するのか

署名鍵(秘密鍵)は 署名者しか持っていない。検証は誰でもできる(公開鍵が公開されているから)。だから「正しく検証できる署名」が存在する = その秘密鍵の持ち主(本人)が署名した と数学的に保証されます。これが法的に「電子署名」として通用する根拠で、日本の電子署名法(2001 年)、EU の eIDAS 規則(2014 年)などはこの暗号原理に立脚しています。

つながる知識: 否認防止が成立するには 秘密鍵が本人だけに保持されている 前提が必要。盗難・漏洩があれば成立しない。だから HSM(Hardware Security Module)TPMSecure Enclave(Apple)、YubiKey などのハードウェア鍵管理が重要視されます。

確認: 次のうち、MAC では実現できないがディジタル署名で成立する、もっとも本質的な性質はどれか。

正解:C。MAC は共有鍵を持つ 2 者ならどちらでも作れるため、署名者を客観的に同定できず否認可能。ディジタル署名は秘密鍵の保有者しか作れないので、第三者にも署名者を立証できる ─ これが MAC との本質的な差で、電子契約・コードサイニングが MAC ではなく署名を使う理由。完全性と認証は両者とも提供する。

標準的な署名スキーム ─ ハッシュ + 公開鍵

ディジタル署名はほぼ全て同じパターンに従います:「メッセージをハッシュで縮める → そのハッシュ値に対して秘密鍵で署名」。検証は逆順:「公開鍵で署名から元のハッシュを導出 → 受信メッセージのハッシュと比較」
POINT 署名生成:
1. h = SHA-256(message)
2. signature = Sign(秘密鍵, h)
送信:(message, signature) のペアを送る(message は平文)

署名検証:
1. h' = SHA-256(received_message)
2. h_from_sig = Verify(公開鍵, signature)
3. h' == h_from_sig なら OK、違えば改ざんまたは偽造

署名の流れを図で

署名:アリスが署名 → ボブが検証 アリス側(署名生成) message: "I, Alice, agree to ..." SHA-256 h = a3f8...e2 秘密鍵で署名 signature = (256 bytes) message + signature を そのままボブに送る 送信 ボブ側(検証) received: "I, Alice, agree to ..." SHA-256 h' = a3f8...e2 公開鍵で検証→h" h' == h" ? → OK / NG 一致 → 改ざんなし、本人の署名 不一致 → 改ざん or 偽造

図の見方:メッセージは平文で運ばれる(暗号化したいなら別途行う)。重要なのは「署名」だけが秘密鍵で作られ、それを公開鍵で検証する流れ。改ざんされたら h' が変わって検証失敗、偽造には秘密鍵が必要なので作れない。

なぜハッシュを挟むのか

考えてみよう: もし弱い MD5 のような壊れたハッシュを使ったら?攻撃者は同じハッシュを持つ別の文書を作って「正規の署名付き偽文書」を成立させられる。これが SHA-1 が証明書から廃止された決定的理由。署名の安全性はハッシュの衝突耐性に依存しています。

Q. もしハッシュを挟まず、メッセージそのものに RSA-2048 で直接署名しようとしたら何が起きるか? 具体的な不都合を 2 つ挙げよ。

主要なディジタル署名アルゴリズム

主流の署名アルゴリズムは大きく RSA 系楕円曲線系 の 2 系統。それぞれ古典と現代があります。

主要 4 アルゴリズムの比較

アルゴリズム鍵長署名長速度(署名/検証)主な用途
RSA-PSS2048〜4096 bit256〜512 B遅い / 速いX.509 証明書(従来)
ECDSA(P-256)256 bit~72 B速い / 速いX.509 証明書(現代)、Bitcoin
Ed25519256 bit64 B非常に速い / 速いSSH、Git、TLS、WireGuard
EdDSA / Ed448448 bit114 B速い高セキュリティ

RSA-PKCS#1 v1.5 vs RSA-PSS

RSA で署名するときは 必ずパディング が必要。古い方式 PKCS#1 v1.5 は決定論的(同じメッセージ → 同じ署名)で、過去に多くの実装脆弱性(Bleichenbacher 攻撃等)が見つかった。RSA-PSS(Probabilistic Signature Scheme) は確率的(ランダムソルトを混ぜる)で、安全性証明もある現代的なパディング。新規システムでは RSA-PSS を使う

ECDSA の落とし穴

ECDSA は 署名のたびに新しい乱数 k を生成する必要 があり、k を予測されたり再利用したりすると 秘密鍵が漏洩 する。Sony PlayStation 3 の鍵漏洩事件(2010)はこれが原因(同じ k を 2 回使った)。RFC 6979 の「決定論的 ECDSA」 は k をハッシュから決定論的に導出することで乱数生成器の脆弱性を回避します。

Ed25519 ─ なぜモダンの一強

2011 年に djb・タンジャ・ランゲらが発表した Ed25519(EdDSA on Curve25519)は ECDSA の問題を構造的に排除した設計:

SSH(OpenSSH 6.5+)、Git(2017+)、WireGuard、Tailscale、Signal など 新しいシステムはほぼ全て Ed25519。RFC 8709(SSH)、RFC 8032(EdDSA)。

確認: Sony PlayStation 3 の署名鍵が漏洩した事件(2010)の直接の原因として、最も適切なものはどれか。

正解:B。ECDSA は署名のたびに新しい乱数 k を生成する必要があり、同じ k で 2 つの異なるメッセージに署名すると、得られる 2 つの署名から連立方程式で秘密鍵が一意に逆算できる。Sony は実装で k を固定値にしていた。Ed25519(EdDSA)や RFC 6979 の決定論的 ECDSA はこの問題を構造的に排除している。

X.509 証明書 ─ ディジタル署名の最大ユースケース

ディジタル署名が世界で最も広く運用されている現場は X.509 証明書。HTTPS の鍵マークの裏で行われているのは「サーバの公開鍵 + 識別情報を、CA がディジタル署名で証明する」という、本講で見てきた仕組みそのものです。証明書のフィールド構成・チェーン検証アルゴリズム・ルートストア・失効と OCSP といった運用面は 標準 #31 TLS と PKI で詳しく扱うので、本講ではディジタル署名の視点から要点だけ押さえます。
POINT X.509 = 「公開鍵 + 識別情報 + 有効期限」をひとまとめにしたデータ構造を、CA の秘密鍵で前節のスキーム(ハッシュ + 公開鍵)で署名 したもの。署名アルゴリズムは RSA-PSS / ECDSA / Ed25519 のいずれか。検証は CA の公開鍵で行う ─ 本講の前半で見た署名検証そのもの。

「サーバ証明書 → 中間 CA → ルート CA」の チェーン・オブ・トラスト も、各段が前段の証明書の中身に対するディジタル署名であり、ルート CA だけが 自己署名(ブラウザ / OS に事前 install されている)。つまり PKI の階層構造そのものが、本講のスキームを縦に積み重ねた応用例と読めます。

Let's Encrypt が変えたもの

2015 年、Let's Encrypt が 無料の自動化された証明書発行 を始めるまで、TLS 証明書は年額数千〜数万円する商用サービスでした。これにより HTTPS の普及率が劇的に上がり(2014 年:~30% → 2024 年:~85%)、Web 全体が暗号化された流れの引き金になりました。中身は ECDSA(P-256) または RSA-PSS で、X.509 と CA 階層の仕組みは変わらず ─ 「ディジタル署名の自動化された大量生産」 が起きたと言えます。

Q. なぜ X.509 では「中間 CA」を挟む 3 段構造になっているのか? ルート CA が直接サーバ証明書に署名すれば 2 段で済むのに、わざわざ中間 CA を入れる理由を 2 つ挙げよ。

コードサイニング ─ ソフトウェアに署名する

アプリ・ドライバ・パッケージなどの ソフトウェア配布物に署名 し、改ざんされていないこと・正規の発行者であることを利用者が検証できるようにする仕組み。OS が積極的に検証を行い、署名のないソフトを警告またはブロックすることで、マルウェアの侵入を防ぎます。

主要なコードサイニングプラットフォーム

OS / 場所仕組み強制度
macOS / iOSApple の Developer ID + notarization(自動マルウェア検査 + Apple 署名)署名なしは警告 / iOS は完全ブロック
WindowsAuthenticode(X.509 で配布物を署名)、SmartScreen が評判ベースで判断未署名は警告。ドライバは強制必要
AndroidAPK 署名 v2/v3。鍵は開発者管理署名必須(自己署名で OK)
Linux パッケージRPM/DEB は GPG 署名。リポジトリ所有者の鍵で署名apt/dnf は鍵検証必須
Git コミットSSH 鍵 / GPG 鍵で git commit -S任意。GitHub では「Verified」表示

Git の SSH 署名(2022〜)

Git 2.34 から SSH 鍵でコミット署名できるようになり、GitHub の verified 表示にも対応。Ed25519 の SSH 鍵で:

# SSH 鍵を署名鍵として設定
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub

# コミットに署名
git commit -S -m "fix: bug in module"

# 署名を確認
git log --show-signature

つながる知識: 2020 年の SolarWinds 事件、2017 年の NotPetya は 署名されたソフトウェアの配布 が攻撃ベクタになりました(攻撃者がビルドサーバを侵害して署名鍵で偽署名)。コードサイニングが信頼できるのは 署名鍵が安全に管理されている前提 でのみ。HSM・Sigstore のような 証明書透明性ログ を組み合わせる動きが進んでいます。

もっと詳しく:Sigstore ─ コード署名を「公開ログ可能」にする

従来のコードサイニングは「署名鍵を信頼する」モデル。鍵が漏れたら攻撃者が正規ソフトに偽装できる(SolarWinds のシナリオ)。Sigstore(Linux Foundation, 2021〜) はこれを「署名イベントを公開ログに記録する」モデルに転換した。

Kubernetes、Python(PyPI)、npm が順次採用中。重要なのは「鍵を長期保管しない」「署名行為そのものが公開される」という設計の根本的な変更で、攻撃者がこっそり署名できる従来モデルとは前提が違う。

OpenSSL ハンズオン ─ 署名と検証

1. RSA 鍵で署名・検証

# 鍵を生成(前回作ったものを使う)
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out rsa_priv.pem
openssl rsa -in rsa_priv.pem -pubout -out rsa_pub.pem

# 署名対象
echo "I, Alice, agree to terms" > doc.txt

# 署名(SHA-256 + RSA-PSS)
openssl dgst -sha256 -sign rsa_priv.pem \
    -sigopt rsa_padding_mode:pss \
    -sigopt rsa_pss_saltlen:32 \
    -out doc.sig doc.txt

# 検証(成功すると "Verified OK")
openssl dgst -sha256 -verify rsa_pub.pem \
    -sigopt rsa_padding_mode:pss \
    -sigopt rsa_pss_saltlen:32 \
    -signature doc.sig doc.txt

2. 改ざんすると検証失敗

# 1 文字書き換える
echo "I, Alice, agree to TERMS" > doc.txt

# 検証 → 失敗
openssl dgst -sha256 -verify rsa_pub.pem \
    -sigopt rsa_padding_mode:pss \
    -sigopt rsa_pss_saltlen:32 \
    -signature doc.sig doc.txt
# → "Verification Failure"

3. Ed25519 で署名(モダン推奨)

# Ed25519 鍵生成
openssl genpkey -algorithm Ed25519 -out ed_priv.pem
openssl pkey -in ed_priv.pem -pubout -out ed_pub.pem

# Ed25519 は内部でハッシュ含むので -sha256 不要(指定するとエラー)
openssl pkeyutl -sign -inkey ed_priv.pem -rawin -in doc.txt -out doc.sig

# 検証
openssl pkeyutl -verify -pubin -inkey ed_pub.pem -rawin -in doc.txt -sigfile doc.sig
# → "Signature Verified Successfully"

4. Python で Ed25519 署名

# pip install cryptography
from cryptography.hazmat.primitives.asymmetric.ed25519 import (
    Ed25519PrivateKey, Ed25519PublicKey
)

# 鍵生成
priv = Ed25519PrivateKey.generate()
pub = priv.public_key()

message = b"I, Alice, agree to terms"

# 署名
signature = priv.sign(message)
print(signature.hex())  # → 64 バイトの署名

# 検証(失敗すると InvalidSignature 例外)
try:
    pub.verify(signature, message)
    print("Valid")
except Exception:
    print("Invalid")

5. 証明書を確認する

# Web サイトの証明書チェーンを取得
openssl s_client -connect example.com:443 -showcerts < /dev/null \
    | openssl x509 -text -noout

# 出力で確認できるもの:
#   Subject: CN=example.com
#   Issuer:  CN=DigiCert TLS Hybrid ECC SHA384 2020 CA1
#   Signature Algorithm: ecdsa-with-SHA384
#   Public Key Algorithm: id-ecPublicKey  (ECDSA P-384)
#   Validity: ...

PQC 署名 ─ 量子時代に向けて

第37回で扱った通り、RSA・ECDSA・Ed25519 はすべて Shor アルゴリズムで破られる。署名は 長期に有効な性質(コードサイニングや法的署名は数年〜数十年検証される)を求められるため、暗号化以上に PQC 移行が急務。NIST は 2024 年に PQC 署名アルゴリズムを正式標準化しました。
POINT NIST 標準化された PQC 署名(2024):
ML-DSA(旧 Dilithium) ─ 格子ベース。FIPS 204。汎用
SLH-DSA(旧 SPHINCS+) ─ ハッシュベース。FIPS 205。安全性根拠が単純
FN-DSA(旧 Falcon) ─ 格子ベース、署名サイズが小さい(NTRU)

特徴:鍵・署名サイズが 古典より数十〜数百倍大きい(Dilithium 公開鍵 1.3 KB、署名 2.4 KB)

サイズ比較

アルゴリズム公開鍵署名備考
Ed25519(古典)32 B64 B現代主流
RSA-3072(古典)~400 B~384 BX.509 で広く使用
ML-DSA-65(PQC, Dilithium)1.95 KB3.3 KBNIST 標準
SLH-DSA-128s(PQC, SPHINCS+)32 B~7.8 KB署名はかなり大きい
FN-DSA(PQC, Falcon)~900 B~666 Bサイズ最小

PQC 署名の実装状況(2024)

「現役の SSH 鍵を 今すぐ Dilithium に移行」までの段階ではないが、長期保存される署名(コードサイニング、法的文書のタイムスタンプ)は次の数年で PQC 移行が進む見込み。

つながる知識: 暗号化(機密性)で「Harvest Now, Decrypt Later」が問題なのと違い、署名は「過去の署名は守れる」のがまだ救い。重要なのは 新規発行する署名 をいつ PQC に切り替えるか。例えば 30 年有効な政府発行のコードサイニング証明書を今 ECDSA で発行すると、20 年後に量子計算機が来た時点で 偽造可能 になる。だからこそ長期署名から先行移行が始まっています。

確認: なぜディジタル署名は「暗号化以上に PQC 移行が急務」と言われるのか? 最も適切な理由を選べ。

正解:C。コードサイニングや法的署名は数年〜数十年検証され続ける。今 30 年有効な署名証明書を ECDSA で発行すると、20 年後に量子計算機が登場した時点で偽造可能になる。「現役の SSH 鍵を急いで Dilithium に」より、「長期保存される署名」を先に移行すべき、というのが現在の優先順位。A は事実だが理由ではない。B は誤り(PQC 暗号化と署名は同時に標準化された)。D は誤り(優先順は使用ケース次第)。

まとめと用語チェック

SUMMARY 1. ディジタル署名 = ハッシュで縮める → 秘密鍵で署名 → 公開鍵で検証
2. 提供する 3 性質:完全性 / 認証 / 否認防止(暗号化は別)
3. MAC との違いは 否認防止 ─ 鍵の非対称性ゆえ署名者を客観的に同定
4. 主要アルゴリズム:RSA-PSS / ECDSA / Ed25519(モダン推奨)
5. X.509 証明書 = サーバ公開鍵に CA が署名 → CA 階層をルートまで辿るのがチェーン
6. コードサイニング(Apple notarization・Authenticode・Git 署名)で配布物を保護
7. PQC 署名(Dilithium・SPHINCS+) は 2024 年標準化、長期署名から移行開始

用語チェック

用語1行説明
ディジタル署名秘密鍵で印を付け、公開鍵で誰でも検証できる仕組み
否認防止(non-repudiation)署名者が「自分が作ったのではない」と否認不可
RSA-PSS確率的パディング。新規 RSA 署名の標準
RSA-PKCS#1 v1.5古い決定論的パディング。新規採用は非推奨
ECDSA楕円曲線版 DSA。Bitcoin・X.509 で使用
Ed25519 / EdDSAdjb 設計のモダン署名。SSH・Git・WireGuard で標準
X.509 証明書公開鍵 + 識別情報 + CA 署名のセット
チェーン・オブ・トラストサーバ証明書 → 中間 CA → ルート CA の署名連鎖
ルート CAOS/ブラウザに同梱の自己署名証明書。信頼の起点
コードサイニングソフトウェア配布物への署名(Authenticode 等)
AuthenticodeWindows のコード署名仕組み
notarizationApple の自動マルウェア検査 + 署名
SigstoreOSS のコード署名の透明性ログプラットフォーム
HSMHardware Security Module。署名鍵を機器内で守る
ML-DSA(Dilithium)NIST FIPS 204(2024) 標準の PQC 署名
SLH-DSA(SPHINCS+)FIPS 205。ハッシュベースの PQC 署名
暗号 5 連発のしめくくり: 第26〜30回で「歴史と OTP」 から始まり、現代の「機密性」と「完全性」の両軸、その実現に使う「共通鍵」「公開鍵」「ハッシュ」「署名」までをすべて見ました。次回 第25回 TLS と PKI 以降、この5本柱が 実際にどう組み合わさってインターネットを守っているか を見ていきます。各章の OpenSSL ハンズオンを順に試して、「教科書の数式が手元のバイト列になる」体験をぜひ。

確認問題

問1. ディジタル署名が MAC に対して持つ 本質的な利点 として、最も適切なものはどれか。

次の選択肢から最も適切なものを選択してください。
A. 計算が速い
B. 暗号化と同時にできる
C. 否認防止が成立する(署名者本人しか作れないので「自分ではない」と否認できない)
D. 鍵が短くて済む
正解:C
MAC は共有秘密鍵を持つ 2 者ならどちらでも作れるので、客観的に署名者を同定できない。ディジタル署名は秘密鍵を持つ本人しか作れないので、法的にも有効な「あなたが作った」という証明 になる。これが電子契約・コードサイニング・証明書で MAC ではなく署名が使われる理由。

問2. 標準的なディジタル署名の生成手順として、最も適切なものはどれか。

次の選択肢から最も適切なものを選択してください。
A. メッセージを公開鍵で暗号化 → 秘密鍵で復号
B. メッセージをハッシュで縮める → そのハッシュを秘密鍵で署名
C. メッセージを共通鍵で暗号化 → ハッシュを足す
D. メッセージそのものを公開鍵で暗号化する
正解:B
ディジタル署名は「ハッシュで圧縮 → 秘密鍵で署名」が標準パターン。直接メッセージに署名すると速度・サイズ的に非現実的なので、必ずハッシュを挟む。これにより 1 GB のファイルでも 32 バイトのハッシュを署名するだけで済む。

問3. Ed25519(EdDSA)が ECDSA より好まれる理由として、最も 適切でない ものはどれか。

次の選択肢から「適切でない」記述を選択してください。
A. 決定論的なので乱数生成器の脆弱性で秘密鍵が漏れる心配がない
B. サイドチャネル攻撃に対して構造的に強い
C. 署名サイズが 64 バイト固定で扱いやすい
D. 量子計算機にも耐えられる
正解:D(これだけ誤り)
Ed25519 は楕円曲線ベースなので、Shor アルゴリズムで 完全に破られる。量子耐性は持たない。そのため将来は Dilithium や SPHINCS+ などの PQC 署名へ移行が必要。A・B・C は全て Ed25519 が ECDSA より優れる本物の理由。

問4. X.509 証明書の「チェーン・オブ・トラスト」について、正しい記述はどれか。

次の選択肢から最も適切なものを選択してください。
A. サーバ証明書は中間 CA に署名され、中間 CA はルート CA に署名され、ルート CA は OS/ブラウザに事前 install されている自己署名証明書
B. すべての証明書は同じルート CA で署名される
C. ブラウザは毎回 CA に問い合わせて検証する
D. 中間 CA は不要で、ルート CA がサーバ証明書に直接署名する
正解:A
チェーンは サーバ → 中間 CA → ルート CA の階層構造。ルート CA は自己署名で、OS/ブラウザ出荷時から信頼ストアに入っている。中間 CA を挟むことで、ルート CA を直接ネットに晒さずに済む(ルート鍵が漏れたら全証明書が無効化される大事故になるため)。

問5. NIST が 2024 年に標準化した PQC 署名アルゴリズム の組として、正しいものはどれか。

次の選択肢から最も適切なものを選択してください。
A. Kyber, Curve25519, Falcon
B. RSA, ECDSA, Ed25519
C. ML-DSA(Dilithium), SLH-DSA(SPHINCS+), FN-DSA(Falcon)
D. AES-256, ChaCha20, Poly1305
正解:C
2024 年に NIST が FIPS 204(ML-DSA = Dilithium)、FIPS 205(SLH-DSA = SPHINCS+)、FIPS 206(FN-DSA = Falcon) として PQC 署名を正式標準化。Kyber(ML-KEM, FIPS 203) は鍵交換用なので含まれない。B は古典署名、D は共通鍵暗号系。
← PREV
第38回 ハッシュ関数・MAC
TOP →
トップへ戻る