🖊️

Digital Signatures

ECDSA · EdDSA · Schnorr · Threshold · Post-Quantum

From elliptic-curve mathematics through NIST FIPS 186-5 standards
to SystemVerilog hardware accelerators and Python implementations

Modern Cryptography Series — Presentation 06  |  ← / → to navigate  |  Esc overview

Roadmap

01–04 Foundations
Why sign? · Properties · Threat model · Hash-then-sign paradigm
05–08 Classical Schemes
DSA lineage · ECDSA deep dive · Schnorr signatures · EdDSA / Ed25519
09–10 Advanced Protocols
Threshold & multi-sig (MuSig2, FROST) · Blind & ring signatures
11–12 Standards & Real-World
FIPS 186-5 · RFC 8032 · BIP 340 · TLS 1.3 · Blockchain
13–14 Hardware
ECDSA/EdDSA FPGA cores · ASIC accelerators · Side-channel countermeasures
15–16 Post-Quantum & Code
ML-DSA (FIPS 204) · SLH-DSA (FIPS 205) · Python · SystemVerilog

Why Digital Signatures?

A digital signature binds a message to a signer's identity with three guarantees:

🔒

Authentication

Only the holder of the private key can produce a valid signature for the associated public key.

🛡️

Integrity

Any modification to the signed message — even a single bit flip — invalidates the signature.

📜

Non-Repudiation

The signer cannot credibly deny having signed, since only their private key could have produced the signature.

Contrast with MACs: A Message Authentication Code (HMAC) provides authentication and integrity, but not non-repudiation — both parties share the same secret key, so either could have produced the tag.

Anatomy: Hash-then-Sign

All modern signature schemes follow the hash-then-sign paradigm:

Message m Hash SHA-256 / SHA-512 h = H(m) Sign(h, privKey) EC scalar mul + mod arithmetic Private Key d Signature (r, s) or (R, s)
Why hash first?
① Reduces arbitrary-length message to fixed-size digest
② Prevents existential forgery attacks on raw signing
③ Hides message structure from the EC arithmetic
Verification mirror:
Verifier recomputes h = H(m) and checks the signature against the public key. No private key needed — only the corresponding public key Q = d·G.

The DSA Family Tree

ElGamal Signature (1985) DSA — FIPS 186 (1994) Schnorr (1989/1991) ECDSA — ANSI X9.62 (1999) Deprecated for signing in FIPS 186-5 (2023) EdDSA — RFC 8032 (2017) BIP 340 Schnorr (2021) FIPS 186-5 (2023) + deterministic ECDSA Ed25519 Ed448
Key insight: All these schemes derive from ElGamal's 1985 framework. The core idea is the same — prove knowledge of a private scalar d by constructing a relationship between a random nonce point, the message hash, and the public key — but they differ in how the relationship is computed and what security proofs are available.

ECDSA: Key Generation

Given agreed-upon domain parameters (CURVE, G, n):

Private key:   d  ←  random integer in [1, n − 1]
Public key:   Q = d · G    (EC point multiplication — the trapdoor)

NIST P-256 (secp256r1)

Field: 𝔽p where p = 2256 − 2224 + 2192 + 296 − 1
Order: n ≈ 2256 (256-bit private keys)
Security: 128-bit (vs. 3072-bit RSA)
Usage: TLS 1.3, PIV cards, AWS KMS, FIDO2

secp256k1 (Bitcoin)

Field: 𝔽p where p = 2256 − 232 − 977
Order: n ≈ 2256
Cofactor: h = 1 (prime order, no subgroup issues)
Usage: Bitcoin, Ethereum, many blockchains

The ECDLP trapdoor: Computing Q = d·G is fast (~0.3 ms in software). Recovering d from Q requires solving the Elliptic Curve Discrete Logarithm Problem — infeasible for properly chosen curves (~2128 group operations with Pollard's rho).

ECDSA: Signing Algorithm

To sign message m with private key d:

Step 1.   e = H(m)    // e.g. SHA-256(m), truncated to bit-length of n
Step 2.   k ← random in [1, n−1]    // CRITICAL: must be fresh & secret per signature
Step 3.   (x₁, y₁) = k · G    // random curve point
Step 4.   r = x₁ mod n    // if r = 0, go back to Step 2
Step 5.   s = k⁻¹ · (e + r · d) mod n    // if s = 0, go back to Step 2

Signature = (r, s)    // two integers, each ≤ 256 bits for P-256
Nonce reuse = catastrophic key leak. If the same k is used for two different messages m₁, m₂ yielding signatures (r, s₁) and (r, s₂), an attacker can recover the private key:
k = (e₁ − e₂) · (s₁ − s₂)⁻¹ mod n  →  d = (s₁ · k − e₁) · r⁻¹ mod n
This exact flaw was exploited in the 2010 Sony PS3 signing key extraction, where k was static.

ECDSA: Verification Algorithm

Given message m, signature (r, s), and public key Q:

Step 1.   Check r, s ∈ [1, n−1]
Step 2.   e = H(m)
Step 3.   w = s⁻¹ mod n
Step 4.   u₁ = e · w mod n   ;    u₂ = r · w mod n
Step 5.   (x₁, y₁) = u₁ · G + u₂ · Q    // Shamir's trick for dual scalar mul
Step 6.   Accept if x₁ mod n = r

Why it works — the correctness proof

Substitute Q = d·G and s = k⁻¹(e + r·d) into the verification equation:

u₁·G + u₂·Q = (e·w)·G + (r·w)·(d·G) = w·(e + r·d)·G = (s⁻¹)·(s·k)·G = k·G

The x-coordinate of k·G is exactly r, so the check passes. ✓

Deterministic ECDSA — RFC 6979

Eliminates the random nonce k entirely, making signatures reproducible and safe from RNG failures.

k = HMAC-DRBG(private_key ‖ H(message))

How it works

① Compute message hash h₁ = H(m)
② Initialize HMAC-DRBG with seed = privKey ‖ h₁
③ Generate candidate k via HMAC-SHA256 iterations
④ If k ∈ [1, n−1] and r ≠ 0 and s ≠ 0, accept
⑤ Otherwise, reseed and retry

Properties

Same (key, message) → same signature
No RNG required at signing time
k is unique per (key, message) pair
Approved in FIPS 186-5 § 6.3.2
Determinism can ease fault injection attacks

FIPS 186-5 status: Both randomized and deterministic ECDSA are approved. Deterministic is preferred for constrained devices without quality RNG; randomized is preferred when fault-injection resistance is critical.

Schnorr Signatures

Proposed by Claus-Peter Schnorr in 1989. Simpler, provably secure under the Random Oracle Model, and crucially — linear.

Sign(m, d):
k ← random in [1, n−1]
R = k · G
e = H(R ‖ P ‖ m)   // key-prefixed
s = k + e · d  mod n
σ = (R, s)   // or (rx, s) — 64 bytes
Verify(m, σ, P):
e = H(R ‖ P ‖ m)
Check: s · G = R + e · P

Advantages over ECDSA

Provable security — reduces to ECDLP in ROM
Linearity: s₁ + s₂ is valid for P₁ + P₂
→ enables native multi-signatures (MuSig2)
Non-malleable — unique (R, s) per (m, d, k)
Batch verification — verify n sigs faster than n × single
Fixed 64-byte encoding (vs. DER 70-72 bytes for ECDSA)

BIP 340 (Bitcoin Taproot): Adopted Schnorr over secp256k1 with x-only 32-byte public keys, tagged hashes for domain separation, and implicit even Y coordinates.

EdDSA — Ed25519 & Ed448

A Schnorr variant on twisted Edwards curves, designed by Bernstein et al. (2011). Deterministic nonce, constant-time, misuse-resistant.

Key generation:
seed ← 32 random bytes
(a, prefix) = SHA-512(seed)
  a: clamp bits (clear 0,1,2,255; set 254)
A = a · B   // public key (32 bytes)
Sign(m, seed):
r = SHA-512(prefix ‖ m) mod ℓ   // deterministic nonce!
R = r · B
h = SHA-512(R ‖ A ‖ m) mod ℓ
S = (r + h · a) mod ℓ
σ = (R, S)   // 64 bytes
Verify:
h = SHA-512(R ‖ A ‖ m) mod ℓ
Check: S · B = R + h · A

Ed25519 Parameters

Curveedwards25519: −x² + y² = 1 + dx²y²
Field𝔽p, p = 2255 − 19
Order ℓ2252 + 27742…336 (≈252 bits)
Cofactorh = 8
HashSHA-512
Key size32 bytes private, 32 bytes public
Sig size64 bytes
Security~128-bit
Deterministic nonce: The nonce r is derived from hashing the private key prefix with the message. No RNG needed at signing time — immune to the PS3/Android Bitcoin nonce-reuse class of attacks.

Scheme Comparison

Property ECDSA EdDSA (Ed25519) Schnorr (BIP 340)
Curve familyWeierstrass (P-256, secp256k1)Twisted Edwards (ed25519, ed448)Weierstrass (secp256k1)
NonceRandom (or RFC 6979)Deterministic (always)Aux-randomized
Signature size70–72 bytes (DER) / 64 (raw)64 bytes64 bytes
Public key size33 bytes (compressed)32 bytes32 bytes (x-only)
Provable securityNot in standard modelROM (Schnorr-based)ROM
Signature malleabilityYes (s → n − s)NoNo
Batch verificationNot nativelyYesYes
Multi-signatureComplexPossibleNative (MuSig2, FROST)
Public key recoveryYes (save bandwidth)NoNo
FIPS approvedFIPS 186-5FIPS 186-5Not yet
Speed (sign, ed25519 ≈ 1.0×)~1.2×1.0×~1.1×

Multi-Signatures & Threshold Signing

Schnorr's linearity enables n-of-n and t-of-n signing protocols that produce a single standard signature.

MuSig2 (n-of-n)

① Each signer i has keypair (dᵢ, Pᵢ)
② Aggregate key: Pagg = Σ aᵢ · Pᵢ  (with key aggregation coefficients aᵢ to prevent rogue-key attacks)
③ Each signer provides two nonces per round (only 2 rounds!)
④ Partial signatures: sᵢ = kᵢ + e · aᵢ · dᵢ
⑤ Final: s = Σ sᵢ   → standard Schnorr sig (R, s)

Verifier sees single 64-byte signature, indistinguishable from solo Schnorr sig.

FROST (t-of-n)

Flexible Round-Optimized Schnorr Threshold signatures allow any t of n participants to produce a valid signature.

① Distributed key generation (DKG) — each party gets a share
② Signing requires only t signers (2-round protocol)
③ Result: standard Schnorr signature — verifier is unaware of threshold

USE CASE Custody wallets, institutional signing, key escrow, MPC-TSS

Blind & Ring Signatures

Blind signatures: Signer signs without seeing the message — used in anonymous credential schemes and e-cash (Chaum, 1983).
Ring signatures: Prove membership in a set without revealing which member signed — used in Monero (CryptoNote) for transaction privacy.

Standards Landscape

StandardAlgorithmsStatusKey Usage
FIPS 186-5 (2023) RSA-PSS, ECDSA, EdDSA Current US federal, TLS, code signing, PKI
RFC 6979 Deterministic DSA/ECDSA Active Constrained devices, test reproducibility
RFC 8032 Ed25519, Ed25519ph, Ed448 Active SSH, TLS 1.3, GnuPG, Signal, WireGuard
SP 800-186 Curve parameters (P-256, P-384, ed25519, ed448) Current Companion to FIPS 186-5
BIP 340 Schnorr over secp256k1 Bitcoin Bitcoin Taproot (activated Nov 2021)
FIPS 204 (2024) ML-DSA (CRYSTALS-Dilithium) PQC Post-quantum replacement for ECDSA
FIPS 205 (2024) SLH-DSA (SPHINCS+) PQC Hash-based PQ signatures (conservative)
FIPS 186-5 key change: DSA is deprecated for new signatures (retained only for verification of legacy data). EdDSA (Ed25519, Ed448) added as FIPS-approved for the first time. Deterministic ECDSA explicitly approved per RFC 6979.

Where Signatures Live

🌐

TLS 1.3

Server certificates signed with ECDSA P-256 or Ed25519. ~95% of HTTPS connections use EC-based signatures. Certificate Transparency logs record every signed cert.

Blockchain

Bitcoin: ECDSA (secp256k1) + Schnorr (Taproot). Ethereum: ECDSA with public key recovery (saves 32 bytes per tx). Solana, Cosmos: Ed25519.

🔑

SSH / GPG

OpenSSH defaults to Ed25519 since 2014. GnuPG supports Ed25519 since 2.1. FIDO2/WebAuthn uses ECDSA P-256 for hardware security keys.

📱

Mobile / IoT

Apple Secure Enclave: ECDSA P-256. Android Keystore: ECDSA. ARM TrustZone: ECDSA/EdDSA via hardware crypto accelerators.

📦

Code Signing

Windows Authenticode, macOS codesign, Android APK signing, Linux kernel module signing — all use digital signatures to prevent supply-chain attacks.

🏛️

PKI / Certificates

X.509 certificate chains: Root CA → Intermediate CA → Leaf. Each link is a digital signature (RSA or ECDSA) binding an entity to its public key.

Hardware: ECDSA/EdDSA Accelerators

Digital signature operations are bottlenecks in TLS handshakes, blockchain validation, and IoT authentication. Hardware acceleration is essential.

ECDSA Accelerator Block Diagram Host / Bus Controller FSM SHA-256 Engine TRNG / DRBG Nonce gen Modular Arithmetic Unit Add / Sub Multiply Inversion Montgomery EC Point Arithmetic Point Add Point Double Scalar Mul (Montgomery Ladder) Key Storage

FPGA Results (Literature)

PlatformCurveSignVerifySlices
Virtex-5K-1630.27 ms0.54 ms18.5k
Virtex-6B-1630.8 ms0.4 ms~13k LUT
Alveo U250P-2560.76 ms~50k LUT

ASIC Results

ProcessAreaFreqPower
45nm CMOS0.257 mm²532 MHz63 mW
45nm (ECC only)0.121 mm²990 MHz39 mW

Key bottleneck: EC scalar multiplication dominates ~90% of signing time. Montgomery ladder preferred for constant-time (SPA-resistant) operation.

Side-Channel Attacks & Countermeasures

Signature implementations leak secrets through timing, power, and electromagnetic emanations.

Attack Vectors

Timing attacks: Non-constant-time modular inversion or conditional branches during scalar multiplication reveal bits of k or d.

Simple Power Analysis (SPA): Single power trace distinguishes point-add (P+Q) from point-double (2P) in the double-and-add ladder.

Differential Power Analysis (DPA): Statistical correlation across many traces recovers key bits.

Electromagnetic (EM) attacks: Near-field probes capture leakage from on-chip wires.

Fault injection: Voltage glitches or laser pulses skip instructions or corrupt intermediate values, enabling Bellcore-style attacks on deterministic ECDSA.

Countermeasures

Constant-time code: No data-dependent branches or memory lookups. Ed25519 is designed for this — all operations are uniform.

Montgomery ladder: Always performs both add and double, eliminating SPA distinguishability.

Scalar blinding: Replace d with d + r·n (same result mod n, but randomized trace).

Point blinding: Add random point before scalar mul, subtract after.

Coordinate randomization: Multiply projective coordinates by random λ — changes power profile without affecting result.

Redundant computation: Dual-rail logic, error detection codes for fault resistance. ~20% area overhead.

Post-Quantum: ML-DSA & SLH-DSA

Shor's algorithm breaks ECDSA/EdDSA/Schnorr on a cryptographically relevant quantum computer. NIST has standardized replacements.

ML-DSA — FIPS 204 (2024)

Based on Module Learning With Errors (MLWE) lattice problem.
Derived from CRYSTALS-Dilithium submission.

Parameter SetSecurityPKSigSK
ML-DSA-44128-bit1,312 B2,420 B2,560 B
ML-DSA-65192-bit1,952 B3,293 B4,032 B
ML-DSA-87256-bit2,592 B4,595 B4,896 B

Sign: ~100 µs (software). Verify: ~50 µs. Competitive with ECDSA for speed, but much larger keys and signatures.

SLH-DSA — FIPS 205 (2024)

Based on hash functions only (SPHINCS+).
Conservative assumption: only needs hash collision/preimage resistance.

Parameter SetSecurityPKSig
SLH-DSA-128s128-bit32 B7,856 B
SLH-DSA-128f128-bit32 B17,088 B
SLH-DSA-256s256-bit64 B29,792 B

Very slow signing (~100 ms) but tiny public keys. s = small sigs, f = fast signing.

Size penalty: An Ed25519 signature is 64 bytes. ML-DSA-44 is 2,420 bytes (38×). This is a major concern for bandwidth-constrained protocols (blockchains, IoT). Hybrid schemes combining classical + PQ signatures are being deployed during the transition.

Interactive: ECDSA Signing Simulator

Simplified ECDSA over a tiny curve for educational purposes. Uses a toy prime field.





Press "Sign" to generate an ECDSA signature...

Toy curve: y² = x³ + 2x + 3 mod 97, Generator G = (3, 6), order n = 5 (very small for demonstration). Real ECDSA uses 256-bit primes.

Python: Ed25519 Signing


import hashlib, os

# --- Ed25519 via Python's standard library (3.6+) ---
from cryptography.hazmat.primitives.asymmetric.ed25519 import (
    Ed25519PrivateKey, Ed25519PublicKey
)
from cryptography.hazmat.primitives import serialization

# Key generation
private_key = Ed25519PrivateKey.generate()
public_key  = private_key.public_key()

# Sign
message   = b"Digital signatures are provably secure"
signature = private_key.sign(message)  # 64 bytes, deterministic

print(f"Public key : {public_key.public_bytes_raw().hex()}")
print(f"Signature  : {signature.hex()}")
print(f"Sig length : {len(signature)} bytes")

# Verify
try:
    public_key.verify(signature, message)
    print("✓ Signature valid")
except Exception:
    print("✗ Signature INVALID")

# Tamper test
try:
    public_key.verify(signature, b"Tampered message!")
    print("✓ Signature valid")       # Should NOT reach here
except Exception:
    print("✗ Tampered message detected — signature invalid")
  

Python: ECDSA (P-256) Low-Level


from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend

# Key generation on NIST P-256
private_key = ec.generate_private_key(ec.SECP256R1(), default_backend())
public_key  = private_key.public_key()

# Extract private scalar d
d = private_key.private_numbers().private_value
print(f"Private key d: {d:#066x}")

# Sign (uses RFC 6979 deterministic nonce internally)
message   = b"ECDSA on NIST P-256"
signature = private_key.sign(message, ec.ECDSA(hashes.SHA256()))

print(f"Signature (DER): {signature.hex()}")
print(f"DER length: {len(signature)} bytes")  # 70-72 bytes

# Decode (r, s) from DER
from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature
r, s = decode_dss_signature(signature)
print(f"r = {r:#066x}")
print(f"s = {s:#066x}")

# Verify
public_key.verify(signature, message, ec.ECDSA(hashes.SHA256()))
print("✓ ECDSA signature verified")
  

SystemVerilog: Modular Inverse

The modular inverse k⁻¹ mod n is the most expensive non-EC operation in ECDSA signing. Fermat's little theorem: k⁻¹ = kn−2 mod n.


module mod_inverse #(
    parameter int WIDTH = 256
)(
    input  logic                clk,
    input  logic                rst_n,
    input  logic                start,
    input  logic [WIDTH-1:0]    k,        // value to invert
    input  logic [WIDTH-1:0]    n,        // modulus (curve order)
    output logic [WIDTH-1:0]    k_inv,    // k^{-1} mod n
    output logic                done
);
    // Fermat's little theorem: k^{-1} = k^{n-2} mod n
    // Uses Montgomery modular exponentiation (square-and-multiply)

    logic [WIDTH-1:0] exp;       // exponent = n - 2
    logic [WIDTH-1:0] base_reg;  // current base (squared each cycle)
    logic [WIDTH-1:0] result;    // accumulator
    logic [$clog2(WIDTH)-1:0] bit_idx;
    logic running;

    assign exp = n - 2;

    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            done    <= 1'b0;
            running <= 1'b0;
        end else if (start) begin
            base_reg <= k;
            result   <= {{(WIDTH-1){1'b0}}, 1'b1};  // 1
            bit_idx  <= '0;
            running  <= 1'b1;
            done     <= 1'b0;
        end else if (running) begin
            // Square-and-multiply: check bit_idx of exponent
            if (exp[bit_idx])
                result <= mont_mul(result, base_reg, n);
            base_reg <= mont_mul(base_reg, base_reg, n);
            if (bit_idx == WIDTH - 1) begin
                running <= 1'b0;
                done    <= 1'b1;
            end
            bit_idx <= bit_idx + 1;
        end
    end

    assign k_inv = result;

    // Montgomery multiplication (simplified — see Presentation 01)
    function automatic logic [WIDTH-1:0] mont_mul(
        input logic [WIDTH-1:0] a, b, m
    );
        // ... full Montgomery reduction pipeline ...
        return (a * b) % m;  // placeholder for synthesis
    endfunction
endmodule
  

SystemVerilog: ECDSA Sign Top-Level


module ecdsa_sign_top #(
    parameter int N = 256  // Curve order bit-width
)(
    input  logic             clk, rst_n, start,
    input  logic [N-1:0]     msg_hash,    // e = H(m), pre-computed
    input  logic [N-1:0]     priv_key,    // d
    input  logic [N-1:0]     nonce_k,     // k (from TRNG or RFC 6979)
    // Curve parameters loaded via config registers (omitted)
    output logic [N-1:0]     sig_r,
    output logic [N-1:0]     sig_s,
    output logic             valid
);
    typedef enum logic [2:0] {
        IDLE, SCALAR_MUL, CALC_R, MOD_INV, CALC_S, DONE
    } state_t;

    state_t state;
    logic [N-1:0] kG_x;       // x-coord of k·G
    logic [N-1:0] k_inv;      // k^{-1} mod n
    logic ec_done, inv_done;

    // Sub-modules (instantiation ports abbreviated)
    ec_point_mul   #(.N(N)) u_pmul  (.*);  // k·G → (kG_x, kG_y)
    mod_inverse    #(.WIDTH(N)) u_inv(.*);  // k^{-1} mod n

    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) state <= IDLE;
        else case (state)
            IDLE:       if (start) state <= SCALAR_MUL;
            SCALAR_MUL: if (ec_done)  state <= CALC_R;
            CALC_R: begin
                sig_r <= kG_x % curve_n;  // r = x₁ mod n
                state <= (sig_r == 0) ? IDLE : MOD_INV;
            end
            MOD_INV:    if (inv_done) state <= CALC_S;
            CALC_S: begin
                // s = k⁻¹ · (e + r·d) mod n
                sig_s <= mont_mul(k_inv,
                    mont_add(msg_hash, mont_mul(sig_r, priv_key)));
                state <= (sig_s == 0) ? IDLE : DONE;
            end
            DONE: begin valid <= 1'b1; state <= IDLE; end
        endcase
    end
endmodule
  

Performance Comparison

ImplementationAlgorithmSignVerifyThroughput
OpenSSL 3.x (x86-64)ECDSA P-256~55 µs~175 µs~18k sign/s
OpenSSL 3.x (x86-64)Ed25519~42 µs~115 µs~24k sign/s
libsodium (x86-64)Ed25519~32 µs~88 µs~31k sign/s
Bitcoin Core (x86-64)Schnorr secp256k1~48 µs~52 µs~19k verify/s
FPGA Virtex-5ECDSA K-163~270 µs~540 µs~1.8k sign/s
FPGA Alveo U250ECDSA P-256~760 µs~1.3k verify/s
ASIC 45nmECDSA B-163~6 µs~160k sign/s
Software (ref)ML-DSA-44~100 µs~50 µs~10k sign/s
ASIC PQ (12nm)ML-DSA-87~97 µs~58 µs~10k sign/s
Key takeaway: Software Ed25519 is the fastest classical scheme. ASICs can achieve 160k+ signatures/second for ECDSA. ML-DSA hardware is catching up — post-layout ASIC results show competitive latency with ~10× larger area than ECDSA accelerators.

Notable Attacks & Failures

Sony PS3 (2010)

Sony used a static nonce k for signing PS3 firmware updates with ECDSA. The fail0verflow group recovered the private key instantly using the nonce-reuse equation. Result: full PS3 jailbreak, homebrew code execution.

Android Bitcoin Wallets (2013)

Android's SecureRandom had a flaw producing insufficient entropy for ECDSA nonces. Multiple Bitcoin wallets generated duplicate k values, allowing attackers to extract private keys and steal funds.

ROCA (2017)

Infineon TPMs generated RSA keys with low-entropy primes. Though not ECDSA-specific, it demonstrates how hardware RNG flaws undermine any signature scheme. Estonian e-ID cards were vulnerable.

Minerva (2019)

Timing side-channel in a smart card's ECDSA implementation leaked nonce bits through variable-time modular reduction. ~10,000 signatures were enough to recover the private key via lattice attacks (Hidden Number Problem).

Lesson: The mathematics of ECDSA/EdDSA are sound. Nearly all real-world breaks exploit implementation failures: bad RNG, nonce reuse, non-constant-time code, or faulty hardware. EdDSA's deterministic nonce eliminates the largest class of these failures by design.

Key Takeaways

Core Concepts

▸ Digital signatures provide authentication, integrity, and non-repudiation
▸ All modern schemes use hash-then-sign over elliptic curve groups
▸ ECDSA, EdDSA, and Schnorr are all rooted in ElGamal's framework
▸ The ECDLP trapdoor: Q = d·G is easy; recovering d from Q is infeasible
▸ Nonce security is paramount — reuse leaks the private key

Recommendations

Best Ed25519 for new systems (fast, deterministic, misuse-resistant)
Good ECDSA P-256 for FIPS compliance and existing infrastructure
BTC Schnorr (BIP 340) for Bitcoin/Taproot ecosystems
Future ML-DSA for post-quantum readiness (FIPS 204)

Standards

FIPS 186-5 (2023): ECDSA + EdDSA approved; DSA deprecated
RFC 8032: Ed25519 & Ed448 specification
RFC 6979: Deterministic ECDSA nonce generation
FIPS 204/205 (2024): ML-DSA & SLH-DSA for post-quantum

Hardware

▸ EC scalar multiplication dominates ~90% of sign/verify time
▸ Montgomery ladder preferred for constant-time (SPA-resistant) operation
▸ ASIC 45nm achieves ~160k ECDSA signatures/second
▸ Post-quantum ML-DSA accelerators emerging (0.23 mm², 1.2 GHz)

References

Standards:
FIPS 186-5, Digital Signature Standard (2023)
NIST SP 800-186, Elliptic Curve Domain Parameters (2023)
RFC 6979, Deterministic DSA/ECDSA (2013)
RFC 8032, Edwards-Curve Digital Signature Algorithm (2017)
BIP 340, Schnorr Signatures for secp256k1 (2021)
FIPS 204, Module-Lattice-Based Digital Signature Standard (2024)
FIPS 205, Stateless Hash-Based Digital Signature Standard (2024)

Papers:
ElGamal, "A Public Key Cryptosystem…" IEEE ToIT (1985)
Schnorr, "Efficient Signature Generation…" J. Cryptology (1991)
Johnson, Menezes, Vanstone, "The ECDSA," IJIS (2001)
Bernstein et al., "High-speed high-security signatures," CHES (2011)
Nick, Ruffing, Seurin, "MuSig2," CRYPTO (2021)
Komlo, Goldberg, "FROST," SAC (2020)
Ducas et al., "CRYSTALS-Dilithium," TCHES (2018)

Implementation:
libsodium — Ed25519 reference library
OpenSSL 3.x — ECDSA/EdDSA provider
Bitcoin Core — secp256k1 + Schnorr library
"Fast Hardware Implementation of ECDSA" — IEEE (2016)
"Lightweight HW Accelerator for PQ Digital Signature" — IACR ePrint (2022)