デジタル署名(ECDSA / EdDSA / RSA-PSS)の理論と Python 実装:nonce の危険性・EUF-CMA・決定的署名を解説

デジタル署名 (ECDSA / EdDSA / RSA-PSS) の理論・比較・Python実装を体系解説。hash-and-sign・EUF-CMA・nonce 再利用攻撃・RFC 6979 決定的 nonce・Ed25519・PKCS#1 v1.5 と PSS の違いを、フルスクラッチ ECDSA (sign/verify) と cryptography ライブラリの実装例で解説。

なぜデジタル署名を学ぶか

デジタル署名 (digital signature) は、「メッセージが本当にその送信者から来たこと(真正性)」「途中で改ざんされていないこと(完全性)」「送信者があとから『署名していない』と言い逃れできないこと(否認防止)」を数学的に保証する仕組みです。TLS のサーバ証明書、JWT の ES256 / RS256、SSH のホスト鍵認証、Git のコミット署名、Bitcoin / Ethereum のトランザクション、OS のコード署名 —— 現代インフラの信頼はほぼすべて署名の上に成り立っています。

署名は公開鍵暗号の応用です。RSA 暗号が素因数分解、楕円曲線暗号 (ECC)が楕円曲線離散対数問題 (ECDLP) に依拠するのと同じ数学的困難性を、今度は「秘密鍵の持ち主だけが作れて、公開鍵で誰でも検証できるタグ」を作るために使います。本記事では、署名の一般モデルと安全性概念 (EUF-CMA) を整理したうえで、実務の三大方式 ECDSA / EdDSA (Ed25519) / RSA-PSS を数式で比較し、Python で教育用フルスクラッチ ECDSA を実際に実行して署名生成→検証成功→改ざん検知まで確認します。暗号領域全体の地図は暗号技術ロードマップを参照してください。

署名の基本モデル

デジタル署名方式は 3 つのアルゴリズムの組 \((\mathsf{Gen}, \mathsf{Sign}, \mathsf{Verify})\) で定義されます。

  1. 鍵生成 \(\mathsf{Gen}\) : セキュリティパラメータから鍵ペア \((sk, pk)\) を生成する。\(sk\) は署名鍵(秘密)、\(pk\) は検証鍵(公開)。
  2. 署名 \(\mathsf{Sign}(sk, m) \to \sigma\) : 秘密鍵とメッセージ \(m\) から署名 \(\sigma\) を生成する。
  3. 検証 \(\mathsf{Verify}(pk, m, \sigma) \to \{0, 1\}\) : 公開鍵で \((m, \sigma)\) の正当性を判定する。

正当な署名は必ず受理される、という正当性 (correctness) が要求されます。

\[ \Pr[\mathsf{Verify}(pk, m, \mathsf{Sign}(sk, m)) = 1] = 1 \tag{1} \]

hash-and-sign パラダイム

実際の署名方式は、メッセージ \(m\) をそのまま署名するのではなく、まず暗号学的ハッシュ関数 \(H\) で固定長のダイジェスト \(e = H(m)\) に潰してから署名します。これを hash-and-sign と呼びます。

\[ \sigma = \mathsf{Sign}(sk, H(m)) \tag{2} \]

hash-and-sign には 3 つの利点があります。

  • 任意長メッセージ対応: 署名の数学は固定サイズの入力(RSA なら法 \(N\) 未満の整数、ECDSA なら位数 \(n\) 未満の整数)しか扱えないが、ハッシュで任意長を吸収できる。
  • 性能: 大きなファイルでも 1 回のハッシュと 1 回の署名演算で済む。
  • 安全性の切り分け: \(H\) が衝突耐性を持てば、署名方式の安全性を「短いダイジェストへの署名」に帰着できる。逆に \(H\) が壊れると署名も壊れる(MD5 の衝突で偽造 CA 証明書が作られた 2008 年の事件が典型)。

ハッシュの内部構造はハッシュ関数の記事や実際のハッシュ生成ツールで確認できます。SHA-256 / SHA-512 が現行の標準です。

MAC との違い —— 否認防止

「メッセージが改ざんされていないこと」を保証する仕組みとしては、AES / ChaCha20 の AEADでも使われる MAC (Message Authentication Code)、たとえば HMAC があります。しかし MAC とデジタル署名は決定的に異なります。

観点MAC (HMAC など)デジタル署名
共有秘密鍵(対称)秘密鍵で署名・公開鍵で検証(非対称)
検証者鍵を共有する者だけ公開鍵を持つ誰でも
否認防止なし(両者が鍵を持つため)あり(秘密鍵の持ち主しか作れない)
主な用途セッション内の完全性・認証証明書・契約・公開検証が必要な場面

決定的な差は否認防止 (non-repudiation) です。HMAC タグは送信者と受信者が同じ鍵を共有するため、受信者も同じタグを作れます。したがって「送信者が作った」と第三者に証明できません。一方デジタル署名は、署名を作れるのは秘密鍵の持ち主ただ一人で、検証は公開鍵だけあれば誰でもできます。だから「この人が確かに署名した」を裁判所や第三者にも示せます。証明書 (PKI) や電子契約が署名を使うのはこのためです。関連する信頼モデルはゼロトラストセキュリティセキュリティ資格の記事も参照してください。

安全性概念: EUF-CMA

署名方式の「安全」とは何かを厳密に定めるのが EUF-CMA (Existential Unforgeability under Chosen-Message Attack; 選択文書攻撃に対する存在的偽造困難性) です。次のゲームで攻撃者 \(\mathcal{A}\) が勝てないことを要求します。

  1. チャレンジャーが鍵ペア \((sk, pk)\) を生成し、\(pk\) を \(\mathcal{A}\) に渡す。
  2. \(\mathcal{A}\) は好きなメッセージ \(m_1, m_2, \dots\) を選んで署名オラクルに問い合わせ、署名 \(\sigma_i = \mathsf{Sign}(sk, m_i)\) を得られる(これが「選択文書攻撃」)。
  3. 最後に \(\mathcal{A}\) は、一度も問い合わせていない新しいメッセージ \(m^\*\) に対する有効な署名 \(\sigma^\*\) を出力しようとする。
\[ \Pr[\mathsf{Verify}(pk, m^\*, \sigma^\*) = 1 \; \land \; m^\* \notin \{m_i\}] \le \mathsf{negl}(\lambda) \tag{3} \]

この確率が無視できるほど小さければ EUF-CMA 安全です。「存在的 (existential)」とは「攻撃者にとって都合のよい特定のメッセージでなくても、何か一つでも新しい有効な署名を作れたら負け」という最も厳しい基準を指します。実務で使う署名方式(RSA-PSS, ECDSA, Ed25519)はいずれも、適切な仮定(RSA 仮定・ECDLP・ランダムオラクル)のもとで EUF-CMA 安全であることが証明されています。逆に、後述する ECDSA の nonce 再利用のような実装ミスは、この証明の前提を壊して偽造を可能にします。

ECDSA: 楕円曲線デジタル署名アルゴリズム

ECDSA (Elliptic Curve Digital Signature Algorithm) は、ECC 上の署名方式で、TLS 証明書・SSH・Bitcoin / Ethereum で広く使われます。曲線のドメインパラメータ(素体 \(\mathbb{F}_p\) 、ベースポイント \(G\) 、位数 \(n\) )を固定します。

鍵生成:

  • 秘密鍵 \(d \in [1, n-1]\) をランダムに選ぶ。
  • 公開鍵 \(Q = dG\) (スカラー倍算)。

署名生成 —— メッセージハッシュ \(e = H(m)\) に対して:

  1. 一時乱数 (nonce) \(k \in [1, n-1]\) を選ぶ。
  2. \(R = kG\) を計算し、\(r = R_x \bmod n\) (\(r = 0\) ならやり直し)。
  3. 次を計算する(\(s = 0\) ならやり直し)。署名は \((r, s)\) 。
\[ s = k^{-1}(e + r d) \bmod n \tag{4} \]

署名検証 —— \((r, s)\) が \([1, n-1]\) にあることを確認し:

\[ w = s^{-1} \bmod n, \quad u_1 = e w \bmod n, \quad u_2 = r w \bmod n \tag{5} \] \[ (x, y) = u_1 G + u_2 Q, \qquad x \bmod n \overset{?}{=} r \tag{6} \]

正当性は代入で確認できます。\(s = k^{-1}(e + rd)\) より \(k = s^{-1}(e + rd) = w e + w r d = u_1 + u_2 d\) 。したがって

\[ u_1 G + u_2 Q = u_1 G + u_2 d G = (u_1 + u_2 d) G = k G = R \tag{7} \]

となり、\(x\) 座標が \(r\) に一致します。

nonce k の再利用・バイアスは致命的

ECDSA 最大の落とし穴は nonce \(k\) です。\(k\) は署名ごとに一様ランダムかつ秘密でなければならず、少しでも漏れると秘密鍵が即座に復元されます。

(a) k の再利用: 同じ \(k\) で 2 つの異なるメッセージ \(m_1, m_2\) に署名すると、\(r\) は共通で、

\[ s_1 = k^{-1}(e_1 + rd), \quad s_2 = k^{-1}(e_2 + rd) \tag{8} \]

の 2 式が立ちます。差を取ると \(s_1 - s_2 = k^{-1}(e_1 - e_2)\) から

\[ k = \frac{e_1 - e_2}{s_1 - s_2} \bmod n, \qquad d = \frac{s_1 k - e_1}{r} \bmod n \tag{9} \]

と、nonce \(k\) と秘密鍵 \(d\) が完全に暴露されます。2010 年、Sony の PlayStation 3 はコード署名 ECDSA で \(k\) を定数にしていたため、fail0verflow / geohot によって署名鍵が抽出され、任意コードに正規署名を付けられる事態になりました。

(b) k のバイアス: \(k\) が完全な再利用でなくても、上位ビットが偏る・一部が既知といった部分的な漏れがあるだけで、複数署名から格子攻撃 (lattice attack; Hidden Number Problem を LLL / BKZ で解く) により \(d\) が復元されます。実際、乱数生成器の弱さや不完全な定数時間実装から鍵が抜かれる事故が繰り返し報告されています。

RFC 6979: 決定的 nonce

この構造的危険を断つのが RFC 6979決定的 (deterministic) ECDSA です。\(k\) を乱数生成器に頼らず、秘密鍵 \(d\) とメッセージハッシュ \(H(m)\) から HMAC-DRBG で決定的に導出します。

\[ k = \mathrm{HMAC\text{-}DRBG}(d, H(m)) \tag{10} \]

こうすると、(1) 同じ \((d, m)\) には常に同じ \(k\) 、異なる \(m\) には(暗号学的に)独立な \(k\) が対応し、再利用もバイアスも起きません。(2) 乱数生成器の品質に依存しないため、エントロピー不足の組み込み機器でも安全です。同じ署名が再現できるためテストも容易になります。現代の ECDSA 実装(OpenSSL, cryptography, Bitcoin ライブラリ等)は RFC 6979 を採用しています。ただし決定的 nonce でも、フォールトインジェクション対策として乱数を追加で混ぜる「hedged」方式も提案されています。

EdDSA / Ed25519

EdDSA (Edwards-curve Digital Signature Algorithm)、特に Curve25519 のツイスト Edwards 形上で SHA-512 を使う Ed25519 は、ECDSA の弱点を設計段階で潰した現代的な署名方式です。SSH・Signal・WireGuard・TLS 1.3・Git のデフォルト署名として普及しています。

鍵生成: 秘密の種 (seed) \(sk\) を SHA-512 でハッシュし、前半 32 byte をクランプしてスカラー \(a\) 、後半 32 byte を「prefix」\(\mathrm{pre}\) とする。公開鍵 \(A = aB\) (\(B\) はベースポイント)。

署名生成 —— メッセージ \(M\) に対して:

\[ r = H(\mathrm{pre} \,\|\, M) \bmod \ell, \quad R = rB \tag{11} \] \[ S = (r + H(R \,\|\, A \,\|\, M) \cdot a) \bmod \ell \tag{12} \]

署名は \((R, S)\) (合計 64 byte)。

検証: \(8 S B \overset{?}{=} 8 R + 8 H(R \| A \| M) A\) を確認する。

ここが決定的に重要な点です。Ed25519 の \(r\) は、秘密の prefix とメッセージから決定的に導出されます(式 (11))。つまり ECDSA の nonce \(k\) にあたる値が、乱数生成器を一切使わずに計算されます。これにより:

  • nonce 再利用・バイアスが構造的に不可能 —— RFC 6979 の思想を方式そのものに組み込んでいる。
  • 実装ミス耐性が高い —— Curve25519 の定数時間 Montgomery/Edwards 演算でサイドチャネルにも強く、無効曲線攻撃も設計で排除。
  • 高速 —— バッチ検証や高速な固定ベース乗算に最適化しやすく、同一セキュリティで ECDSA より速いことが多い。
観点ECDSAEd25519 (EdDSA)
nonce乱数(RFC 6979 で決定的化)常に決定的(方式に内蔵)
実装ミス耐性低い(nonce 事故が頻発)高い(misuse-resistant)
曲線P-256 / secp256k1 など可変Curve25519 固定
ハッシュ任意(SHA-256 等)SHA-512 固定
署名長約 64–72 byte (DER)64 byte 固定
速度標準一般に高速

新規プロトコルで曲線ベース署名を選ぶなら、迷わず Ed25519 が 2026 年のベストプラクティスです。ECDSA は既存互換性(TLS 証明書チェーン、Bitcoin の secp256k1 など)が必要な場面で残ります。

RSA 署名: PKCS#1 v1.5 と RSA-PSS

RSAでも署名できます。素朴には、秘密指数 \(d\) でハッシュを「復号」演算にかけ、公開指数 \(e\) で「暗号化」演算をかけ戻して検証します。

\[ \sigma = (H(m))^{d} \bmod N, \qquad \sigma^{e} \bmod N \overset{?}{=} H(m) \tag{13} \]

ただし「教科書 RSA 署名」はそのままでは偽造可能なので、実務ではパディング方式が本質的に重要です。2 つの標準があります。

PKCS#1 v1.5

RSA PKCS#1 v1.5 署名 (RS256 など) は、ハッシュ値の前に固定のパディングバイト列とハッシュアルゴリズム識別子 (ASN.1 DigestInfo) を連結してから累乗します。決定的で実装は単純ですが、パディングが構造的(固定パターン)なため、実装が甘いと Bleichenbacher の署名偽造 (BB'06) のような攻撃を許した歴史があります(公開指数 \(e=3\) かつ検証実装がパディングを厳密チェックしない場合、平方根を取るだけで署名を捏造できた)。理論的な帰着証明も弱く、「安全性が形式的に保証されていない」方式です。それでも JWT の RS256、古い TLS 証明書、多くのレガシーシステムで今なお広く使われています。

RSA-PSS

RSA-PSS (Probabilistic Signature Scheme; RS256 に対する PS256 等) は Bellare–Rogaway による確率的パディングで、ソルト (salt) を混ぜて署名ごとに異なる出力を作ります。MGF1(マスク生成関数)でハッシュを引き延ばし、EMSA-PSS エンコーディングを施してから累乗します。

\[ \mathrm{EM} = \mathrm{EMSA\text{-}PSS\text{-}ENCODE}(H(m), \text{salt}), \qquad \sigma = \mathrm{EM}^{d} \bmod N \tag{14} \]

PSS が推奨される理由:

  • 証明可能安全性: ランダムオラクルモデルで、RSA 仮定に厳密に帰着する EUF-CMA 安全性が証明されている。v1.5 にはこの保証がない。
  • ソルトによる頑健性: 確率的なので、同じメッセージでも毎回異なる署名になり、決定的パディングを狙う攻撃面が消える。
  • 標準の推奨: NIST FIPS 186-5、TLS 1.3、最新の PKI は PSS を推奨・要求する方向。

新規に RSA 署名を実装するなら PSS 一択です。PKCS#1 v1.5 は既存互換性のためだけに残すべきレガシーと位置づけられます。

三方式の比較

項目RSA-PSS (3072 bit)ECDSA (P-256)Ed25519
依拠する困難性素因数分解 / RSA 仮定ECDLPECDLP (Curve25519)
公開鍵長384 byte33 byte (圧縮)32 byte
署名長384 byte約 64–72 byte (DER)64 byte
署名速度遅い速い非常に速い
検証速度非常に速い標準速い(バッチ検証可)
実装難易度中(パディングが要)高(nonce 事故が致命的)低(misuse-resistant)
決定的いいえ(PSS はソルト)乱数(RFC 6979 で決定的化)はい(内蔵)
主な用途レガシー TLS 証明書, JWTTLS, SSH, 暗号通貨, JWTSSH, Signal, WireGuard, Git

大まかな使い分けの指針:

  • 新規プロジェクト: 署名は Ed25519 を第一候補に。曲線互換や既存 PKI の都合があれば ECDSA (P-256)。
  • RSA が必須の環境(HSM や古い認証局): RSA-PSS を選び、v1.5 は避ける。
  • 検証が支配的なワークロード(証明書を大量検証するクライアント): RSA の検証は \(e = 65537\) の軽い累乗なので有利な場合がある。
  • 暗号通貨: Bitcoin / Ethereum は secp256k1 上の ECDSA(Bitcoin は Taproot 以降 Schnorr も採用)。

用途例として、OAuth 2.0 / OIDC の JWT では RS256(RSA v1.5)・PS256(RSA-PSS)・ES256(P-256 ECDSA)・EdDSA(Ed25519)がアルゴリズム識別子として使われます。

Python 実装

1. 教育用フルスクラッチ ECDSA(実行検証済み)

小さな素体上の曲線 \(y^2 = x^3 + 2x + 2 \pmod{17}\) 、ベースポイント \(G = (5, 1)\) (位数 \(n = 19\) )で ECDSA を実装します。数式 (4)〜(6) をそのまま写し、double-and-add でスカラー倍算します。このコードは実際に実行し、署名生成→検証成功→改ざん検知、さらに nonce 再利用による鍵復元まで確認済みです。

import hashlib

# --- 小さな素体上の曲線: y^2 = x^3 + 2x + 2 over F_17 ---
p = 17
a, b = 2, 2
G = (5, 1)   # ベースポイント
n = 19       # G の位数 (この点は位数 19)
O = None     # 無限遠点


def ec_add(P, Q):
    """楕円曲線上の点加算 (逆元は pow(x, -1, p))"""
    if P is O:
        return Q
    if Q is O:
        return P
    x1, y1 = P
    x2, y2 = Q
    if x1 == x2 and (y1 + y2) % p == 0:
        return O  # P + (-P) = O
    if P == Q:
        lam = (3 * x1 * x1 + a) * pow(2 * y1, -1, p) % p  # 接線
    else:
        lam = (y2 - y1) * pow(x2 - x1, -1, p) % p         # 弦
    x3 = (lam * lam - x1 - x2) % p
    y3 = (lam * (x1 - x3) - y1) % p
    return (x3, y3)


def scalar_mult(k, P):
    """double-and-add: O(log k) 回の点演算で kP"""
    R, Q = O, P
    while k:
        if k & 1:
            R = ec_add(R, Q)
        Q = ec_add(Q, Q)
        k >>= 1
    return R


def hash_to_int(msg):
    return int.from_bytes(hashlib.sha256(msg).digest(), "big") % n


def sign(d, msg, k):
    """署名生成: s = k^{-1}(e + rd) mod n  … 式 (4)"""
    e = hash_to_int(msg)
    r = scalar_mult(k, G)[0] % n
    assert r != 0
    s = pow(k, -1, n) * (e + r * d) % n
    assert s != 0
    return (r, s)


def verify(Q, msg, sig):
    """署名検証: u1 G + u2 Q の x 座標が r か  … 式 (5), (6)"""
    r, s = sig
    if not (1 <= r < n and 1 <= s < n):
        return False
    e = hash_to_int(msg)
    w = pow(s, -1, n)
    u1, u2 = e * w % n, r * w % n
    X = ec_add(scalar_mult(u1, G), scalar_mult(u2, Q))
    return X is not O and X[0] % n == r


# --- 鍵生成 ---
d = 7                       # 秘密鍵
Q = scalar_mult(d, G)       # 公開鍵 Q = dG
assert scalar_mult(n, G) is O   # G の位数が n であることの確認

# --- 署名と検証 ---
msg = b"transfer 1 coin to Bob"
sig = sign(d, msg, k=11)
print("公開鍵 Q      =", Q)
print("署名 (r, s)   =", sig)
print("正当な検証    :", verify(Q, msg, sig))                       # True
print("改ざん検知    :", verify(Q, b"transfer 1 coin to Eve", sig)) # False

# --- nonce 再利用 → 秘密鍵復元のデモ (式 (9)) ---
msg2 = b"transfer 2 coin to Bob"
sig2 = sign(d, msg2, k=11)  # 同じ k を再利用 (危険!)
r, s1 = sig
_, s2 = sig2
e1, e2 = hash_to_int(msg), hash_to_int(msg2)
k_rec = (e1 - e2) * pow(s1 - s2, -1, n) % n
d_rec = (s1 * k_rec - e1) * pow(r, -1, n) % n
print("復元した nonce k =", k_rec, "(真値 11)")
print("復元した秘密鍵 d =", d_rec, "(真値 7)")

実行結果:

公開鍵 Q      = (0, 6)
署名 (r, s)   = (13, 14)
正当な検証    : True
改ざん検知    : False
復元した nonce k = 11 (真値 11)
復元した秘密鍵 d = 7 (真値 7)

正当な署名は受理され、1 文字書き換えたメッセージは棄却されます。さらに、同じ nonce \(k = 11\) を 2 回使っただけで、式 (9) の連立方程式から秘密鍵 \(d = 7\) が完全に復元されてしまうことが確認できます。これが PlayStation 3 事件の原理そのものです。なおこの実装は教育用で、実際の曲線の巨大素数・定数時間演算・DER エンコード・厳密な nonce 生成は省いています。

2. 実用ライブラリ: cryptography による ECDSA / Ed25519 / RSA-PSS

本番では検証済みライブラリを使います。以下は cryptography での三方式の署名・検証例です。この環境には cryptography が未インストールのため実行検証はしていません(実運用時に pip install cryptography で導入してください)が、API の使い方の参考になります。

# 注: このコードは cryptography ライブラリが必要 (pip install cryptography)。
#     本記事の実行環境には未導入のため、掲載のみで実行検証はしていない。
from cryptography.hazmat.primitives.asymmetric import ec, ed25519, padding, rsa
from cryptography.hazmat.primitives import hashes
from cryptography.exceptions import InvalidSignature

msg = b"contract: pay 100 USD"

# --- (a) ECDSA (P-256): nonce は RFC 6979 系で内部的に安全生成 ---
ec_key = ec.generate_private_key(ec.SECP256R1())
ec_sig = ec_key.sign(msg, ec.ECDSA(hashes.SHA256()))
ec_key.public_key().verify(ec_sig, msg, ec.ECDSA(hashes.SHA256()))

# --- (b) Ed25519: 決定的署名・API は極めてミニマル ---
ed_key = ed25519.Ed25519PrivateKey.generate()
ed_sig = ed_key.sign(msg)                       # ハッシュ指定も不要
ed_key.public_key().verify(ed_sig, msg)         # 失敗時 InvalidSignature

# --- (c) RSA-PSS: v1.5 ではなく PSS + MGF1 を使う ---
rsa_key = rsa.generate_private_key(public_exponent=65537, key_size=3072)
pss = padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
                  salt_length=padding.PSS.MAX_LENGTH)
rsa_sig = rsa_key.sign(msg, pss, hashes.SHA256())

try:
    rsa_key.public_key().verify(rsa_sig, msg, pss, hashes.SHA256())
    print("all signatures verified")
except InvalidSignature:
    print("verification failed")

ポイント: (a) cryptography の ECDSA は nonce 生成を内部で安全に処理するため、利用側で \(k\) を扱う余地がありません。(b) Ed25519 はハッシュ・曲線・nonce の選択肢すら無く、sign(msg) / verify(sig, msg) だけの最小 API で「間違えようがない」設計です。(c) RSA では padding.PSS(...) を明示し、レガシーな padding.PKCS1v15() を新規では避けます。フルスクラッチ実装が踏む地雷(nonce 事故・パディングオラクル)をライブラリ層が吸収してくれるのが、本番でライブラリを使う最大の理由です。

まとめ

  • デジタル署名は \((\mathsf{Gen}, \mathsf{Sign}, \mathsf{Verify})\) の 3 アルゴリズムで、hash-and-sign により任意長メッセージを固定長ダイジェストに潰してから署名する。
  • MAC と違い否認防止を提供する(秘密鍵の持ち主だけが署名でき、公開鍵で誰でも検証できる)。安全性の基準は EUF-CMA
  • ECDSA は式 (4)〜(6) で成立するが、nonce \(k\) の再利用・バイアスは秘密鍵の即時漏洩に直結する(PlayStation 3 事件・格子攻撃)。RFC 6979 の決定的 nonce で構造的に防ぐ。
  • Ed25519 (EdDSA) は nonce を方式に内蔵して決定化し、実装ミス耐性・速度で ECDSA を上回る。新規プロトコルの第一候補。
  • RSA 署名は PKCS#1 v1.5 ではなく、証明可能安全性を持つ RSA-PSS を推奨。
  • 用途に応じて RSA-PSS / ECDSA / Ed25519 を使い分ける。TLS・JWT・SSH・暗号通貨での実例は比較表を参照。
  • Python では、学習に教育用フルスクラッチ ECDSA(実行検証済み)、本番に cryptographyec / ed25519 / padding.PSS を使う。

関連記事

関連ツール

参考文献

  • Johnson, D., Menezes, A., & Vanstone, S. (2001). “The Elliptic Curve Digital Signature Algorithm (ECDSA)”. International Journal of Information Security, 1(1), 36–63.
  • Bernstein, D. J., Duif, N., Lange, T., Schwabe, P., & Yang, B.-Y. (2012). “High-speed high-security signatures”. Journal of Cryptographic Engineering, 2(2), 77–89.
  • Josefsson, S., & Liusvaara, I. (2017). “Edwards-Curve Digital Signature Algorithm (EdDSA)”. RFC 8032.
  • Pornin, T. (2013). “Deterministic Usage of DSA and ECDSA”. RFC 6979.
  • Bellare, M., & Rogaway, P. (1996). “The Exact Security of Digital Signatures — How to Sign with RSA and Rabin”. EUROCRYPT ‘96.
  • Moriarty, K. et al. (2016). “PKCS #1: RSA Cryptography Specifications Version 2.2”. RFC 8017.
  • NIST (2023). “Digital Signature Standard (DSS)”. FIPS 186-5.