Make a pair of keys, sign a note, then change one character and watch the check fail — then go deeper, into signing that is identical every time and the edge cases a verifier has to screen for.
Start here: sign a note, then change it
A signature proves two things at once: that a note came from you, and that nobody has
altered it since. You need no mathematics to watch that happen — three buttons, in order.
Everything here runs real Ed25519 in your browser; the only thing being hidden is the
notation.
1Make a pair of keys
One key stays secret and does the signing. The other is public — you can hand it to
anyone, and it only lets them check a signature, never make one.
No keys yet.
2Sign a note
Nothing signed yet.
3Check it — then change one character
Checking uses only the public key and the note. Then change a single letter and check
again: the note still reads the same, and the check no longer passes.
Sign a note first.
Show the actual bytes
These are the real values the steps above produced. The panels below work with them
directly.
Public key
Signature
The three panels below are these same three steps with the bytes on show, and after them
the lab goes further: deterministic nonces, and the cofactor-8 edge case where two
correct libraries disagree about the same signature.
1Key Forge
32-byte private seed — never fully displayed in UI
32-byte seed → SHA-512 and pruning → 32-byte compressed public point
public key = [clamped scalar]·G
The seed's clamped SHA-512 prefix is interpreted little-endian. Watch the leading bit and next 12 bits as real double/add operations, then a labelled summary skips the remaining arithmetic and jumps to the exact public point. The endpoint jump is not an add G; plotted coordinates are approximate.
Generate a keypair to walk [scalar]·G.
2Sign
64 bytes: R = bytes 0–31 (a curve point), S = bytes 32–63 (a scalar).
Deterministic check: sign the same message twice
Signature #1
Signature #2
Click "Sign Again" (or edit the message and re-sign) to compare.
3Verify
Enter hexadecimal characters. Spaces and separators are ignored.
Try a failure:
Awaiting keypair, signature, and verification input.
Why this matters
Most signature schemes require a random nonce per signature. If that RNG fails - even once - your private key is exposed. Ed25519 eliminates this entire class of failure by deriving the nonce deterministically from the private key and message. Sony's PlayStation 3 was broken because their ECDSA implementation used a constant nonce. Ed25519 makes that mistake structurally impossible. The "Ed25519 vs ECDSA" tab runs this break live on real P-256: reuse the nonce and watch the private key fall out and forge a signature the real verifier accepts.
Ed25519 vs ECDSA
Ed25519 uses deterministic nonces, derived from private key material and message, so nonce RNG failure cannot expose keys the way bad ECDSA nonce generation can. Its group has cofactor = 8, which affects validation rules and small-subgroup edge cases. Ed25519 is commonly batch-verified, often verifies around 2x faster than P-256 ECDSA in practical stacks, and always outputs compact 64-byte signatures (instead of variable-length DER encoding).
Live: an ECDSA nonce slip leaks the whole private key
This runs on real NIST P-256 in your browser. A fresh keypair signs two different messages. When the nonce k repeats, the two signatures share the same r, and the private key d falls straight out of the algebra — then a brand-new message is signed with the recovered key and handed to the real @noble/curves P-256 verifier. This is the class of bug Ed25519's deterministic nonce makes impossible.
Live: Ed25519 signs the same message twice — measured
The claim that Ed25519 is deterministic is checked, not asserted: the same message is signed twice with a fresh key and the two 64-byte signatures are compared byte-for-byte, right here.
The Math
Ed25519 is built on a twisted Edwards curve of the form −x² + y² = 1 + d·x²y² over a prime field Fp with p = 2²⁵⁵ − 19 (about 255 bits — that "25519" is the prime). The base point G is fixed; your private scalar multiplies G to produce the public point. Scalar multiplication is repeated point addition and doubling.
Note on the picture: unlike the Weierstrass "draw a line, find the third intersection" chord-and-tangent rule you may have seen for secp256k1, twisted Edwards addition uses a single unified algebraic formula that works for every pair of points — even a point added to itself — with no special cases and no exceptional points. That completeness (no branches to leak timing) is a security feature, not just a convenience, which is why the geometric slope diagram is the wrong mental model here. The addition is arithmetic on coordinates:
(x₁,y₁) + (x₂,y₂) = (x₃, y₃)
x₁y₂ + x₂y₁ y₁y₂ + x₁x₂
x₃ = ───────────────── y₃ = ─────────────────
1 + d·x₁x₂y₁y₂ 1 − d·x₁x₂y₁y₂
one formula · all inputs · no exceptions
The Key Forge animation follows the clamped SHA-512 prefix as a little-endian integer. Each displayed arithmetic step doubles or adds G; after the leading bit and next 12 bits, a labelled summary skips the remaining operations and jumps to the exact public key. That jump is not an add G. Plot coordinates are approximate; this teaching walk is not the signing library's execution trace.
Pitfalls & ZIP215
In plain terms: a signature is supposed to prove that someone holding the secret key really signed this exact message. A specially chosen fake public key can break that promise — for some verifiers but not others. Below, you can watch two correct, spec-following libraries look at the identical bytes and disagree on whether they are valid. That disagreement is the whole pitfall.
Before ZIP215-aligned behavior, signature acceptance around edge cases and cofactor clearing could vary by library, enabling practical malleability and consensus disagreement risks. Verifying the same signature in two different libraries could produce conflicting outcomes. Monero was impacted by this class of ambiguity. ZIP215 standardized consensus-safe verification behavior so implementations agree. Reference: ZIP-0215.
Torsion point
A special point that loops back to zero after just a few additions (a "small order"). Real public keys don't do this — that is exactly why one can be used to build a fake.
Cofactor 8
The Ed25519 group is 8 times bigger than the "real" prime-order subgroup used for signing. Those 8 extra copies are where the 8 torsion points live — and where the malleability hides.
[8]·(R + [k]·A − [S]·B) == 0
The cofactored verification check. A is the public key, B the base point, R/S the two halves of the signature. Multiplying by 8 (the cofactor) makes any torsion part of A vanish — which is precisely the hole the forgery drives through.
Live: cofactor malleability
Ed25519's group has cofactor 8, so eight low-order "torsion" points exist. Using one of them as a public key, we can hand the verifier a 64-byte "signature" — split into its R and S halves below — that was never produced by any secret key. The forge trick simply sets R = [S]·B. The two legitimate verification rules then disagree on the identical bytes:
Small-order public key (hex)
Crafted signature (hex)
ZIP215 (noble default, cofactored)—
Strict RFC 8032 / FIPS 186-5—
The same bytes: accepted by one rule, rejected by the other. This is real — run it and inspect the two outputs. It also shows why systems that treat signatures as unique IDs must reject small-order keys.
Where It's Used
Ed25519 appears in Signal, SSH (supported by OpenSSH since 6.5 in 2014, the ssh-keygen default since 9.5 in 2023), TLS 1.3 deployments, and Zcash-related systems. The age encryption tool is a partial exception: its native recipients are X25519, and it accepts ssh-ed25519 keys only as an interoperability path. Ethereum account signatures use secp256k1, while consensus-layer cryptography in adjacent ecosystems often involves BLS-style primitives.