################################################################### EdDSA / Ed25519 — countermeasures ################################################################### :Spec: RFC 8032 :cite:`rfc8032` :Crate path: ``arcana::ecc::eddsa`` :Cargo feature: none — Ed25519 is unconditionally compiled. Ed448 is **planned but not yet implemented** (RFC 8032 Appendix A port pending). EdDSA is **structurally** more SCA-friendly than ECDSA — the nonce is HMAC-derived from the secret, the scalar is well-formed by construction (no rejection sampling), and the scalar multiplication is on a Twisted-Edwards curve where the unified addition formulas avoid the special cases of Weierstrass addition. In return, EdDSA's deterministic nature (:cite:`rfc8032`) makes it the textbook target of single-fault key-recovery attacks (:cite:`romailler2017eddsa_fault`). .. contents:: :local: :depth: 2 Coverage matrix =============== .. list-table:: EdDSA countermeasure / threat matrix :header-rows: 1 :widths: 25 18 57 * - Threat - Status - Countermeasure(s) * - SPA on Ed25519 scalar mul - **partial — audit pending** - The Ed25519 scalar multiplication path in ``ecc::eddsa::ed25519_sign`` calls into ``ecc::eddsa::scalar_mul_*`` which is **separate** from the Weierstrass ``scalar_mul_point``; needs its own audit. Item ``T1-F``. * - DPA on scalar mul - **vulnerable** - Plan ``T2-A`` is shared with the Weierstrass side (Z-rerand on the projective coordinates). * - Single-fault on deterministic Ed25519 - **vulnerable** - Plan ``T1-D``: hedged Ed25519 mode (RFC 8032 + 32 bytes additional randomness, mirroring :cite:`cfrg_hedged_sigs`). * - Template attacks on Ed25519 (:cite:`samwel2018ed25519_wolfssl`) - **vulnerable** - Plan ``T2-A`` (Z-rerand) + ``T2-B`` (scalar blinding). * - Power analysis on intermediate hash digest (the SHA-512 of ``sk || M``) - **partial** - Plan ``T2-D``: SHA-512 itself is not masked; the carry-based DPA result of :cite:`belenky2023_cdpa_hmac_sha2` extends to plain SHA-2, so this is a real surface. Discussion in :doc:`hmac` (HMAC chapter, since the same SHA-512 primitive is used). Background — Ed25519 signing flow ================================= Ed25519 derives the per-signature nonce ``r`` deterministically: .. math:: H(\mathrm{seed}) &= h \;\|\; \mathrm{prefix} \\ r &= H(\mathrm{prefix} \;\|\; M) \bmod \ell \\ R &= r \cdot B \\ k &= H(R \;\|\; A \;\|\; M) \bmod \ell \\ s &= r + k \cdot a \bmod \ell where ``a`` is the secret scalar derived from the seed (= the truncated, clamped form of the upper half of ``H(seed)``), ``A = a · B`` is the public key, and ``B`` is the Edwards generator. The single-fault attack (Romailler-Pelissier :cite:`romailler2017eddsa_fault`): * Sign ``M`` once normally → ``(R, s)``. * Inject a fault during the second signing of ``M`` so ``r`` changes: e.g. glitch one byte of the SHA-512 state → ``r' ≠ r``. * The fault produces ``(R', s')`` with ``r ≠ r'`` but the **same challenge** ``k`` (since ``k = H(R || A || M)`` and ``R`` changed too — but this is what the attacker observes). Actually the standard formulation: glitch *one* of the two signatures so it's effectively non-deterministic. From two non-equal ``r`` for the same message, the attacker recovers ``a = (s - s') / (k - k') mod ℓ`` (modulo factor adjustments). **One fault → key recovery.** Single-fault → key recovery (``T1-D``) ====================================== The countermeasure is the same as the ECDSA side: hedged signing. The CFRG draft :cite:`cfrg_hedged_sigs` already specifies the EdDSA variant. Implementation hooks: * New ``ed25519_sign_hedged(sk, msg, rng) -> Signature`` API. * Internally: .. math:: r = H(\mathrm{prefix} \;\|\; \rho \;\|\; M) \bmod \ell where ``ρ`` is 32 bytes of fresh randomness; everything else unchanged. * Pure-Ed25519 deterministic stays available for KAT compatibility (RFC 8032 §7.1 vectors must keep verifying bit-for-bit). * Tests: KAT regression for the deterministic path; randomized round-trip for the hedged path; fault unit test asserting two ``ed25519_sign_hedged`` calls on the same message yield different ``R``-components. This item is the same as the ECDSA-side ``T1-D``; the two share the ``rng`` plumbing and the API design. SPA / DPA on the Edwards scalar multiplication (``T1-F``, ``T2-A``) ==================================================================== Audit gap --------- The Ed25519 scalar multiplication code in ``arcana::ecc::eddsa::scalar_mul_*`` was written before the Weierstrass-side hardening (commit 76191c1) and has not been re-audited under the same lens. Specific items to check: 1. **Branch-free ladder**: confirm the loop body uses ``ct_swap`` between two accumulator points, not a window method that conditionally selects from a precomputed table. 2. **No early exit on Z = 0**: the Edwards twisted formula :math:`(X : Y : Z : T)` (extended coordinates) does not have the "point at infinity" issue of Weierstrass — the neutral element ``(0, 1, 1, 0)`` is just a normal point. So this particular issue does not arise; confirm anyway. 3. **Constant-time clamping**: the secret scalar is clamped per RFC 7748 (clear bits 0/1/2/255, set bit 254). The clamping itself uses bitwise ops, no branches; confirm. 4. **``black_box`` shielding** on the Curve25519 field ``reduce_p`` — same pattern as the Weierstrass side. Item ``T1-F``: full audit pass mirroring what was done for Weierstrass in 76191c1. Estimated effort: 2 days. Z-coordinate randomization -------------------------- Edwards curves admit the same Z-rerandomization technique as Weierstrass: .. math:: (X, Y, Z, T) \;\sim\; (\lambda X, \lambda Y, \lambda Z, \lambda T), \qquad \lambda \stackrel{\$}{\leftarrow} \mathbb{F}_p^* Implementation route is identical to ``ecdsa_ecdh.rst`` ``T2-A``: draw ``λ`` from an internal SCA-RNG before the ladder, scale all four extended coords. Cost: 4 field multiplications; ~< 1 % overhead. Scalar blinding works the same way: ``a' = a + r · ℓ`` for ``ℓ = 2^252 + 27742317777372353535851937790883648493``, the order of the prime-order subgroup. Reading list ============ * :cite:`romailler2017eddsa_fault` — the canonical Ed25519 fault attack (FDTC 2017). * :cite:`cao2020_lattice_fault_det_sig` — generalized lattice- based fault attacks across many faulted Ed25519 signatures. * :cite:`samwel2018ed25519_wolfssl` — first practical SCA breaking Ed25519 in WolfSSL via SCA on the SHA-512 step. * :cite:`cfrg_hedged_sigs` — IETF CFRG draft for hedged ECDSA / EdDSA. Code path summary ================= .. list-table:: :header-rows: 1 :widths: 30 35 35 * - Path - Today (2026-04-21) - Target (post T1-D + T1-F + T2-A) * - ``ed25519_sign`` - Pure RFC 8032 deterministic - Unchanged (kept for KAT determinism) * - ``ed25519_sign_hedged`` (new) - n/a - RFC 8032 + 32-byte fresh randomness * - Edwards ``scalar_mul`` - Audit pending - Audited CT + Z-rerand + scalar blinding * - SHA-512 used inside Ed25519 - Audit pending - Same as :doc:`hmac` (CDPA mitigation if T2-D applies) Ed448 ===== Ed448 is **deferred** in arcana (RFC 8032 Appendix A reference Python port pending). When it lands, the same threat-model chapter applies (mutatis mutandis on Curve448 / Goldilocks): hedged mode, Z-rerandomization, scalar blinding. The implementation route is otherwise identical, since Curve448 also admits extended Twisted-Edwards coordinates.