Signatures by the byte: Ed25519, ML-DSA and the rest
How Ed25519 and ML-DSA work at the level an engineer needs, the exact sizes of every NIST option, and why on Solana the size of a signature matters far more than its speed.
- Ed25519 gives a 32-byte public key and a 64-byte signature, deterministic and very fast.
- ML-DSA (FIPS 204) is built on module lattices and comes in three sizes: 44, 65 and 87.
- Even the smallest, ML-DSA-44, has a 1,312-byte public key and a 2,420-byte signature, about 41× and 38× Ed25519.
- SLH-DSA trades very large signatures for hash-only security. Falcon is compact but hard to implement safely.
Ed25519 in one paragraph
Ed25519 is a Schnorr-style signature on the Edwards form of Curve25519. The secret key is a 32-byte seed. Hashing it with SHA-512 yields a secret scalar a and a nonce prefix. The public key is A = a·B, a single 32-byte point. To sign, the signer derives a nonce r from the prefix and the message, so no randomness is needed at signing time. It then publishes R = r·B and S = r + H(R, A, M)·a. The verifier checks S·B = R + H(R, A, M)·A. That is 64 bytes of signature and a few tens of microseconds of work.
Solana uses exactly this for every transaction signer, and an account address is the public key A itself.
How ML-DSA works, roughly
ML-DSA, standardised from CRYSTALS-Dilithium, uses a pattern called Fiat–Shamir with aborts over module lattices. The public key holds a seed that expands into a large matrix A, plus a compressed vector t = A·s₁ + s₂, where s₁ and s₂ are short secret vectors. Recovering them from t is an instance of the Module-LWE problem, which no known quantum algorithm solves efficiently.
To sign, the signer picks a random masking vector y, hashes the message together with the high bits of A·y into a sparse challenge c, and outputs z = y + c·s₁. If z or a related value would reveal anything about the secret, the signer throws the attempt away and tries again, which usually takes a few rounds. The signature is the challenge hash, z and a small hint that lets the verifier rebuild the high bits.
Two details are worth knowing. FIPS 204 signing is “hedged” by default: fresh randomness is mixed with a deterministic seed, so a weak random number generator degrades gracefully instead of leaking the key. And the standard supports a context string of up to 255 bytes, which lets one key sign for different purposes without the signatures being interchangeable.
The byte table
| Scheme | Public key | Secret key | Signature | Sig vs Ed25519 | NIST cat. |
|---|---|---|---|---|---|
| Ed25519 | 32 | 32 | 64 | 1× | — |
| ML-DSA-44 | 1,312 | 2,560 | 2,420 | 37.8× | 2 |
| ML-DSA-65 | 1,952 | 4,032 | 3,309 | 51.7× | 3 |
| ML-DSA-87 | 2,592 | 4,896 | 4,627 | 72.3× | 5 |
| SLH-DSA-SHA2-128s | 32 | 64 | 7,856 | 122.8× | 1 |
| SLH-DSA-SHA2-128f | 32 | 64 | 17,088 | 267.0× | 1 |
| Falcon-512 (FN-DSA) | 897 | 1,281 | 666 | 10.4× | 1 |
Secret-key sizes are less painful than they look. ML-DSA key generation is deterministic from a 32-byte seed, so an implementation can store just the seed and rebuild the full key when needed.
Why size, not speed, is the problem
Optimised ML-DSA verification is in the same range as Ed25519, and signing is not far behind. Run the Lab and you will see JavaScript timings of a few milliseconds at most, apart from SLH-DSA signing. Speed is rarely the blocker.
Bytes are. A Solana transaction is capped at 1,232 bytes, so a single ML-DSA-44 signature is already about twice the whole transaction. A post-quantum signer also has to bring its public key along somewhere, because a 32-byte address can no longer serve as the verification key. Chapter 04 works through what that does to the transaction format.
The other options
SLH-DSA (FIPS 205), standardised from SPHINCS+, builds signatures entirely out of hash functions. If SHA-2 or SHAKE holds up, it holds up; there is no lattice assumption to worry about. The cost is size and signing time: the “s” (small) sets have signatures around 8 KB and sign slowly, the “f” (fast) sets sign faster with signatures around 17 KB.
Stateful hash-based signatures (XMSS and LMS, NIST SP 800-208) are much smaller, but the signer must never reuse a one-time key. That makes them a poor fit for general wallets and a reasonable fit for firmware signing. The simplest member of the family, the Winternitz one-time signature, has been used by community projects on Solana to build vaults that sign exactly once and then move funds to a fresh vault.
FN-DSA (Falcon) has the smallest public key plus signature of the lattice schemes, about 1.5 KB together at level 1. Its signer needs fast, constant-time Gaussian sampling, usually with floating-point arithmetic, which is notoriously hard to implement without side channels. NIST is standardising it as FIPS 206, and the Lab lists it for size only until that is final.
Choosing for a chain
There is no single winner. The questions that decide it for a blockchain are:
- How many signatures go into one transaction or block, and what each one costs in bytes.
- Where the public key lives: in every transaction, once in an account, or behind a hash.
- What verification costs inside the runtime, not just on a laptop.
- How mature and reviewed the implementations are, including side-channel resistance.
- Whether the scheme is a final standard or still a draft.
NIST positions ML-DSA as the general default and SLH-DSA as the conservative fallback. Many teams expect to use both: ML-DSA for everyday keys, hash-based schemes for rarely used, high-value roots.
Sources
- RFC 8032 Edwards-Curve Digital Signature Algorithm (EdDSA)The Ed25519 specification.
- FIPS 204 Module-Lattice-Based Digital Signature StandardML-DSA, the general-purpose signature replacement.
- FIPS 205 Stateless Hash-Based Digital Signature StandardSLH-DSA, the hash-only signature option.
- NIST SP 800-208 Recommendation for Stateful Hash-Based Signature SchemesXMSS and LMS.
- NIST PQC project Post-Quantum Cryptography standardizationStatus of FN-DSA (Falcon) and the other selections.
checked 2026-10 against the documents above
Outside this chapter
- Security proofs and how the parameter sets were derived.
- Side-channel hardening of specific implementations.
- Performance of on-chain verification inside the Solana runtime.