Every SSH key you generate with ssh-keygen -t ed25519 and every WireGuard tunnel that comes up in under a second rests on the same 255-bit curve. But Ed25519 vs X25519 is not a rematch of rivals fighting over the same job. One signs data. The other agrees on a shared secret. Mixing them up is a common source of subtle bugs, and it is also why so many engineers ask which one their protocol actually needs.

This piece breaks down what each primitive does, how fast each runs in 2026 benchmarks, where they show up in production systems like Signal, WireGuard, and OpenSSH, and how to migrate a codebase that has been quietly using the wrong one. Expect real numbers pulled from AWS’s own engineering research, a Java platform performance study published this year, and a hardware-level benchmark run on commodity Linux boxes.

By the end, you should be able to answer a question that trips up a surprising number of interview candidates and code reviewers alike: if a design doc says “use Curve25519,” does that mean Ed25519, X25519, or both? The answer changes depending on whether the system needs to prove identity, agree on a secret, or, as most real systems do, handle both jobs at once.

Ed25519 vs X25519: What Each One Actually Does

Ed25519 is a signature scheme. It takes a message and a private key and produces a 64-byte signature that anyone holding the matching 32-byte public key can verify. It is deterministic, meaning the same message and key always produce the identical signature, which removes an entire class of bugs tied to bad random number generators.

X25519 does something different. It is a Diffie-Hellman key agreement function. Two parties each generate a key pair, exchange public keys, and independently compute the same 32-byte shared secret without ever transmitting it. That secret then feeds a symmetric cipher like AES-256-GCM or ChaCha20-Poly1305 for the actual data encryption.

Both trace back to the same underlying object: Curve25519, the elliptic curve Daniel Bernstein published in 2006. Ed25519 uses its twisted Edwards form for signatures (standardized in RFC 8032), while X25519 uses the Montgomery form for key exchange (standardized in RFC 7748). Same curve, different encoding, different job. That distinction is the entire premise of the Ed25519 vs X25519 comparison, and getting it backward is where most implementation mistakes start.

The Shared Math Behind Two Different Jobs

Twisted Edwards vs Montgomery Form

Curve25519 itself is defined in Montgomery form, which makes scalar multiplication (the core operation in Diffie-Hellman) fast and simple to implement without branching, a property that also helps resist timing attacks. Ed25519 needed the twisted Edwards form instead, because Edwards curves support complete addition formulas, a requirement for building a signature scheme that does not leak information through edge cases in point addition.

The two forms are birationally equivalent, meaning you can convert a point from one to the other with a simple formula. That is why libraries like libsodium and OpenSSL can share large chunks of field-arithmetic code between their Ed25519 and X25519 implementations, even though the public APIs look nothing alike.

Why You Cannot Just Reuse One Key for Both

Developers sometimes ask whether an Ed25519 signing key can double as an X25519 key exchange key, since both are 32 bytes and sit on related math. Filippo Valsorda’s widely cited writeup on this exact question concludes it is possible to derive an X25519 key from an Ed25519 seed, but doing so mixes two security proofs that were never designed to interact, and most cryptography reviewers flag it during audits. The safer, simpler path is to generate a separate key pair for each purpose. Storage cost is trivial, just 32 extra bytes, and it closes off an entire category of cross-protocol attacks.

How One Curve Became Two Standards

Daniel Bernstein published Curve25519 in 2006 as a standalone Diffie-Hellman function, and for years the ecosystem barely distinguished it from what we now call X25519. The name X25519 came later, formalized once RFC 7748 folded Curve25519 and its larger sibling Curve448 into a single specification in 2016. Ed25519 followed a separate track. Bernstein and coauthors published the signature scheme in 2011, and the IETF did not standardize it until RFC 8032 in January 2017, over a decade after the underlying curve first appeared.

That gap explains a lot of the confusion engineers still run into. Early adopters, including the NaCl and libsodium projects, shipped working Ed25519 and X25519 code years before either had an RFC number, using their own naming conventions along the way. By the time formal standards caught up, plenty of production systems had already built assumptions about how the two functions related to each other, some of which turned out to be wrong once auditors started asking pointed questions about key reuse.

Ed25519 vs X25519 Spec Comparison

Here is the side-by-side breakdown engineers usually want before picking one or planning to use both. Keep this table open in a tab the first time you wire either primitive into a new service, since half the mistakes covered later in this article come from mixing up a row from one column with the other.

AttributeEd25519X25519
Primary functionDigital signaturesDiffie-Hellman key exchange
Curve formTwisted Edwards (Edwards25519)Montgomery (Curve25519)
Governing RFCRFC 8032 (EdDSA)RFC 7748 (X25519/X448)
Public key size32 bytes32 bytes
Private key size32-byte seed (expands to 64 bytes)32 bytes
Output size64-byte signature32-byte shared secret
DeterminismDeterministic, no per-signature randomness neededFresh ephemeral key pair typically generated per session
Security level~128-bit~128-bit
X.509 identifiersDefined in RFC 8410, clarified in RFC 9295Defined in RFC 8410, clarified in RFC 9295
NIST statusApproved digital signature scheme under FIPS 186-5Not a NIST-standardized primitive, but widely permitted in TLS profiles
Typical use in TLS 1.3Certificate signatures where supportedEphemeral key agreement (alongside P-256)
Post-quantum statusClassical only, not quantum-resistantClassical only, paired with ML-KEM in hybrid designs
Common librarieslibsodium, OpenSSL 3.x+, Go crypto/ed25519, BoringSSLlibsodium, OpenSSL 3.x+, Go crypto/ecdh, BoringSSL

The two 32-byte public keys look identical on disk, but a program that tries to use an Ed25519 public key inside an X25519 exchange, or the reverse, will either fail outright or, worse, produce a result that looks valid and is not. Type-safe libraries like Go’s crypto/ecdh package intentionally use distinct Go types for exactly this reason.

Benchmark Data From Three Independent Sources

Raw sign/verify throughput cannot be compared head-to-head against key-agreement throughput, since they measure different mathematical operations serving different purposes. What can be compared is how each primitive has improved as engineering teams optimize their implementations, and how each performs in absolute terms on modern hardware.

SourceTest setupResult
Amazon Science (AWS cryptography engineering)Formally verified microarchitecture-specific code paths across three CPU familiesEd25519 signing throughput up 108% on average, X25519 key agreement up 113% on average, with an 86% blended improvement across the evaluated workload
Java platform performance study (2026)Updated field-arithmetic routines for both primitives on JVM buildsX25519 key generation and agreement up 49-54%, Ed25519 keygen, signing, and verification up 46-49% in one configuration, 16-20% in another
Independent ctypes/libsodium benchmark (2026)Raw C bindings called from Python on a single commodity hostEd25519 measured at roughly 4,845 key generations, 3,929 signs, and 7,773 verifies per second

Read those numbers as implementation gains, not as an algorithm race. The AWS team did not make Ed25519 or X25519 mathematically faster. They rewrote the field arithmetic for specific CPU pipelines and formally verified the result stayed constant-time, which matters as much for security as for speed. A 108% throughput jump with no timing-side-channel regression is a harder engineering win than it looks.

One practical takeaway holds across all three sources: both primitives run comfortably in the thousands of operations per second on ordinary server hardware, so for the overwhelming majority of applications, raw throughput is not the constraint. Network latency, database round trips, and TLS handshake overhead will dominate your response times long before Ed25519 or X25519 math becomes the bottleneck.

Hardware also matters more than people expect. The AWS results specifically targeted Graviton and other ARM-based server chips alongside x86 parts, since cloud fleets increasingly mix architectures and a field-arithmetic routine tuned only for one instruction set can quietly become the slow path on the other. If you run a mixed-architecture fleet, benchmark both primitives on each CPU family you actually deploy rather than trusting a single published number.

How Much of the Internet Actually Uses X25519

Adoption numbers for these two primitives are harder to pin down than raw benchmarks, but a few figures give a real picture. Cloudflare reported that among origin connections covered by its automatic key-exchange rollout, roughly 64% still negotiated classical X25519 as of late October 2025, with about 33% already on the hybrid X25519MLKEM768 group and the remainder on other curves. That 64% figure is specific to Cloudflare’s origin-connection cohort, not the entire internet, but it is one of the few named-source numbers available and it shows classical X25519 still carrying the majority of that traffic even as post-quantum hybrids gain ground.

Security track records matter here too. Neither Ed25519’s nor X25519’s underlying math has been broken, but implementations are not immune to bugs. In August 2026, researchers disclosed CVE-2026-76234, covering flaws in the Rust libcrux library: a broken clamping check during X25519 secret-key import, and a duplicated clamping step in libcrux-ed25519’s key generation path. Neither issue broke the algorithms themselves. Both were implementation bugs, fixed in libcrux-ecdh 0.0.6 and libcrux-ed25519 0.0.6, and they are a useful reminder that picking the right primitive is only half the job. The library implementing it needs scrutiny too.

Real-World Deployments: Where Each One Actually Runs

The Ed25519 vs X25519 split shows up clearly once you look at named systems in production.

  • OpenSSH has recommended Ed25519 for user and host keys since OpenSSH 6.5, and by default now generates Ed25519 keys unless told otherwise. It is a signature job, proving you hold the private key, so Ed25519 fits.
  • TLS 1.3 uses X25519 as one of its two mandatory-to-implement groups for the ephemeral key exchange that sets up each session’s symmetric keys, the other being P-256. Certificates riding on top of that handshake can use Ed25519 signatures where the CA and client both support it, so a single TLS session can legitimately touch both primitives at once.
  • WireGuard builds its entire handshake around Curve25519 Diffie-Hellman, which in practice means X25519, to establish the session keys behind its famously short, auditable codebase.
  • Signal’s X3DH and Double Ratchet protocols use X25519 for the repeated Diffie-Hellman operations that keep forward secrecy intact across a conversation, while Ed25519-style signatures authenticate the identity and prekeys exchanged during setup. Signal’s own documentation is explicit that these are separate operations serving separate goals.
  • age, the modern file-encryption tool that has largely replaced ad hoc GPG scripts for developers, uses X25519 as its native public-key recipient format, exactly because the job is key agreement for encrypting a file to someone, not signing.
  • Software signing and artifact verification tools, including minisign and several Sigstore-adjacent workflows, default to Ed25519 because verifying a release artifact is a pure signature problem.
  • GitHub has supported Ed25519 as a valid SSH key type for repository authentication and commit signing for years, and continues to recommend it over RSA in its key-generation documentation for the same reason OpenSSH does.
  • Tailscale, the mesh VPN built on top of WireGuard, inherits WireGuard’s Curve25519-based handshake wholesale, meaning every device-to-device connection on a Tailscale network leans on X25519 key agreement under the hood.

Look at that list and the pattern holds without exception. Anywhere the job is proving something came from you, Ed25519 shows up. Anywhere the job is two parties agreeing on a secret, X25519 shows up. Systems that need both, like TLS 1.3 with client certificates or Signal, simply use both, each for its own half of the problem.

What stands out across every example above is how little friction the split actually causes. None of these products treat picking between Ed25519 and X25519 as an open design question. Each protocol’s spec already settled the choice years ago based on the job at hand, which is a strong signal that the “job first, primitive second” framing this whole comparison rests on is not just a tidy editorial device. It is how working systems are actually built.

Cost and Performance Trade-offs in Production

Neither primitive carries a licensing fee, so there is no pricing table in the traditional sense. What actually costs money is engineering time and compute overhead, and those differ enough between the two to warrant a real comparison. Think of this table as the budget conversation you would have with a security lead before greenlighting either migration, not a vendor quote.

FactorEd25519X25519
Compute cost per operationLow, sign and verify complete in well under a millisecond on server CPUsLow, a single key agreement also completes in well under a millisecond
Memory footprintSmall, fixed-size keys and signatures fit in cache lines easilySmall, identical key size to Ed25519
Integration complexityModerate, requires careful handling of the 64-byte expanded private key format across librariesLow, straightforward Diffie-Hellman API in most crypto libraries
Session overhead added to a TLS 1.3 handshakeNone directly, used for certificate chains rather than per-sessionRoughly 1-2ms per handshake on typical hardware, per prior TLS 1.3 group benchmarking
Migration effort from RSA/ECDSAModerate, requires reissuing certificates and updating trust chainsLow to moderate, mostly a config change in modern TLS stacks
Audit/compliance costLower in FIPS-regulated environments now that FIPS 186-5 approves itHigher in strict FIPS-only shops, since X25519 still lacks dedicated FIPS approval in some certified modules

That last row trips up more teams than any performance number. A shop targeting FIPS 140-3 validation can often adopt Ed25519 signatures cleanly today, while still needing to fall back to P-256 or P-384 for key exchange inside a validated module, even though X25519 is arguably the better engineered option. Check your specific module’s certificate before assuming either primitive is cleared.

Code Example: Generating Both Key Types in Python

Here is a minimal example using the cryptography library that shows both primitives side by side, which makes the API difference concrete.

from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey

# Ed25519: sign and verify a message
signing_key = Ed25519PrivateKey.generate()
message = b"deploy build 4821 to production"
signature = signing_key.sign(message)
signing_key.public_key().verify(signature, message)  # raises if invalid

# X25519: agree on a shared secret between two parties
alice_key = X25519PrivateKey.generate()
bob_key = X25519PrivateKey.generate()

alice_shared = alice_key.exchange(bob_key.public_key())
bob_shared = bob_key.exchange(alice_key.public_key())

assert alice_shared == bob_shared  # both derive the same 32-byte secret

Note the shape of each call. Ed25519 takes a message and returns a signature you check against a public key. X25519 takes someone else’s public key and returns a secret both sides can derive independently. There is no message in the X25519 call because there is nothing being signed, only a secret being agreed on.

Ed25519: Pros and Cons

Pros:

  • Deterministic signatures remove randomness-related failure modes that have caused real key leaks in other schemes, including well-documented ECDSA nonce reuse incidents.
  • Small, fixed-size 64-byte signatures keep certificate chains and JWTs compact.
  • Now formally approved under FIPS 186-5, which opens the door for regulated environments that previously had to avoid it.
  • Wide library support, including native support in OpenSSH, OpenSSL 3.x, and Go’s standard library.

Cons:

  • Cannot be used for key exchange without converting to a Montgomery-form key, a step most security reviewers advise against for production systems.
  • Not quantum-resistant, so it needs a migration plan alongside ML-DSA or SLH-DSA for long-lived signatures.
  • Some older X.509 tooling and hardware security modules still lack full Ed25519 support, which can complicate certificate issuance pipelines.

X25519: Pros and Cons

Pros:

  • Mandatory-to-implement group in TLS 1.3, so it works out of the box with virtually every modern browser and server stack.
  • Simple, branch-free scalar multiplication makes constant-time implementations easier to get right than older curve arithmetic.
  • Forms the classical half of the emerging hybrid post-quantum key exchange defined in RFC 10024, so it stays relevant through the PQC transition.
  • Powers WireGuard’s minimal, widely audited handshake and Signal’s forward-secure ratchet.

Cons:

  • No dedicated FIPS approval in some validated cryptographic modules, which forces P-256 or P-384 as a fallback in strict compliance environments.
  • Like Ed25519, offers no quantum resistance on its own and needs an ML-KEM pairing for long-term confidentiality.
  • Ephemeral key handling adds session-state complexity that a pure signature scheme does not have to deal with.

Migration Guide: Cleaning Up Mixed Curve25519 Usage

Teams that inherited a codebase built before Ed25519 and X25519 had clean library support, roughly pre-2018, often find both primitives tangled together, or worse, a single key pair reused for both jobs. Here is a practical path to untangle it.

  1. Audit every place a Curve25519 key touches your code. Grep for raw 32-byte key handling, not just library calls, since older code sometimes rolls its own wrappers around libsodium’s low-level functions.
  2. Separate signing keys from exchange keys. If you find any code deriving an X25519 key from an Ed25519 seed, or the reverse, replace it with two independently generated key pairs. The storage cost is negligible.
  3. Move to type-safe APIs where available. Go’s crypto/ed25519 and crypto/ecdh packages, or libsodium’s distinct function families, prevent a key of one type from being silently passed to a function expecting the other.
  4. Rotate keys during the split, don’t reuse old material. Treat this as a full key rotation event: generate fresh Ed25519 signing keys and fresh X25519 exchange keys rather than trying to convert old ones.
  5. Update certificate and trust-chain tooling. If you are moving TLS certificate signatures to Ed25519, confirm your CA, HSM, and client libraries all support RFC 8410 identifiers before cutting over in production.
  6. Add automated tests that assert type separation. A unit test that tries to feed an Ed25519 public key into your X25519 exchange path and expects a hard failure catches regressions before they ship.
  7. Roll out behind a feature flag and monitor handshake and signature failure rates, then fully retire the old mixed-key path once error rates hold steady for a full deploy cycle.

For SSH fleets specifically, the rollout is simpler than the TLS case. Generating a fresh host key is a one-line change:

ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""

The harder part is coordinating known_hosts updates across every machine that already trusts the old RSA or ECDSA host key, which is why staged rollouts (adding the new key type alongside the old one before removing anything) beat a hard cutover almost every time.

Budget more calendar time for the certificate side of this migration than the code side. Rewriting a function call takes an afternoon. Getting a new certificate chain trusted across every client your users run does not.

Where Post-Quantum Migration Changes the Picture

Neither Ed25519 nor X25519 survives a sufficiently large quantum computer running Shor’s algorithm. That is not a 2026 discovery, but the migration plans built around it are very much a 2026 story. In August 2026, the IETF published RFC 10024, authored by engineers from PQShield, AWS, Cloudflare, and the University of Waterloo, defining hybrid post-quantum and traditional key agreement for TLS 1.3. The design pairs a classical exchange, commonly X25519, with ML-KEM, the NIST-standardized lattice-based key encapsulation mechanism.

The logic behind hybrid designs is straightforward. If ML-KEM turns out to have an undiscovered flaw, the classical X25519 component still protects the session. If a quantum computer eventually breaks X25519, the ML-KEM component still holds. You lose almost nothing by combining them beyond a modest increase in handshake bytes, and you gain protection against two independent failure modes instead of one.

Signatures face a parallel shift. Ed25519 remains fine for short-lived authentication, but data that needs to stay verifiable for decades, think code-signing keys or long-term certificate authorities, increasingly pairs Ed25519 with, or moves outright to, ML-DSA. The practical rule for 2026 reads simply: keep X25519 and Ed25519 for anything session-scoped or short-lived, and start planning a hybrid or full PQC path for anything that has to remain trustworthy ten or twenty years out.

Turning this on in a modern TLS stack is often a one-line configuration change rather than a rewrite. OpenSSL 3.x and BoringSSL-based servers that support the hybrid group typically just need the group name added to the negotiation list:

# nginx example: prefer the PQC/classical hybrid, keep X25519 as fallback
ssl_ecdh_curve X25519MLKEM768:X25519:prime256v1;

Keep classical X25519 in the fallback list. Older clients that have not shipped ML-KEM support yet will negotiate down to it automatically, and the handshake keeps working for both new and old traffic during the transition window.

Common Mistakes Engineers Make With These Two Primitives

A few patterns show up repeatedly in code review and security audits, and most trace back to treating Ed25519 and X25519 as interchangeable rather than complementary. None of the following require exotic knowledge to avoid. They mostly require someone on the team to actually read the two RFCs before writing the integration code.

  • Reusing one key pair for both signing and key exchange to save a database column. This mixes two distinct security proofs and has been flagged in multiple third-party audits as a design smell, even when no concrete attack is demonstrated.
  • Assuming Ed25519 secures a TLS session by itself. It authenticates a certificate. The session key still comes from a Diffie-Hellman exchange, typically X25519.
  • Skipping signature verification on the fast path because Ed25519 verify calls are cheap. Cheap does not mean optional, and skipping verification under load has caused real incidents in package registries.
  • Hardcoding key type assumptions in serialization formats, so a 32-byte blob gets deserialized as whichever type the code happened to expect, silently corrupting data instead of failing loudly.
  • Forgetting forward secrecy considerations when reusing X25519 ephemeral keys across sessions instead of generating fresh ones, which quietly weakens the whole point of ephemeral key exchange.
  • Trusting an unvalidated public key in either direction. X25519 has a handful of low-order input points that, if not rejected, can force a predictable shared secret, and libraries that skip this check reopen an old, well-documented class of key-exchange bugs.
  • Logging raw key material during debugging and forgetting to strip it before shipping logs to a third-party monitoring service, a mistake that has nothing to do with the math and everything to do with operational discipline.

Ed25519 and X25519 Compared to Other Elliptic Curves

Curve25519’s main competitors are NIST’s P-256 and, in blockchain contexts, secp256k1. All three offer roughly 128-bit security, so the practical differences come down to implementation properties rather than raw strength. P-256 remains the default in many government and enterprise environments because it carries a longer FIPS track record, even though its arithmetic is harder to implement in constant time than Curve25519’s branch-free design. secp256k1 dominates Bitcoin and Ethereum tooling for historical reasons tied to those projects’ early design choices, not because it outperforms Ed25519 for general-purpose signing.

For a new project with no legacy constraint, Ed25519 and X25519 are usually the easier and safer default over either alternative. They were designed from the ground up to avoid the implementation pitfalls, like non-constant-time branching and weak random nonce generation, that have caused real-world incidents with older curve implementations. The tradeoff is narrower support in some older hardware security modules and certain FIPS-only deployments, which is exactly why the earlier compliance-cost comparison flagged that gap.

Use-Case Recommendations

Five scenarios where the choice between Ed25519 vs X25519 is clear-cut, plus guidance for the cases where you genuinely need both.

  • Use Ed25519 if you’re building an SSH key management system, a software release signing pipeline, or a JWT-based authentication service where you need to prove a token’s origin.
  • Use X25519 if you’re building a VPN protocol, a secure messaging app’s session-key setup, or an encrypted file format aimed at replacing ad hoc GPG scripts.
  • Use both if you’re building a TLS-terminating service with client certificate authentication, since the handshake needs X25519 for the session key and can use Ed25519 for the certificate chain.
  • Use X25519 paired with ML-KEM if you’re building anything meant to stay confidential for years, following the hybrid pattern defined in RFC 10024.
  • Use Ed25519 if you’re building a blockchain or distributed ledger component that needs compact, fast-to-verify transaction signatures at scale.
  • Stick with P-256 or P-384 instead of either if your deployment target is a FIPS 140-3 validated module that has not yet certified Curve25519 support, and you cannot wait for recertification.

The Verdict

The data here does not point to a winner because there is no race. Ed25519 and X25519 solve different problems on the same curve family, and the benchmarks from AWS, from the 2026 Java platform study, and from independent testing all confirm both run fast enough that raw speed rarely decides the outcome. What decides the outcome is matching the primitive to the job: signatures for proving identity, key exchange for establishing secrets.

The takeaway: if your system needs to prove who sent something, reach for Ed25519. If it needs two parties to agree on a secret without transmitting it, reach for X25519. Most production systems worth building need both, and the engineering discipline that matters most is keeping them separate, typed, and never substituted for one another.

If you take one number away from this whole comparison, make it this one: Cloudflare’s own telemetry still shows classical X25519 carrying roughly 64% of the origin traffic it measured in late 2025, even as post-quantum hybrids climb. That is not a sign X25519 is fading. It is a sign the industry is layering new protection on top of a primitive that has already earned a decade of trust, rather than throwing it out. Ed25519 is on a similar trajectory on the signature side, gaining a FIPS 186-5 stamp of approval after years of grassroots adoption in SSH and software signing tools. Both primitives got here the same way: not by winning a speed contest, but by doing one job well enough that nobody felt the need to replace them.

Frequently Asked Questions

Is Ed25519 faster than X25519?

They cannot be fairly compared on raw speed because they perform different operations. Independent benchmarks show Ed25519 verification running at roughly 7,773 operations per second on a commodity host, while X25519 key agreement runs in a similar low-millisecond range on comparable hardware. Both are fast enough that neither becomes a bottleneck in typical applications.

Can I use the same key pair for Ed25519 and X25519?

Technically you can derive one from the other since they share the same underlying curve, but most security reviewers and library authors recommend against it. Generating two independent key pairs costs almost nothing in storage and avoids mixing two different security proofs.

Does TLS 1.3 use Ed25519 or X25519?

Both, for different parts of the handshake. X25519 is one of TLS 1.3’s mandatory-to-implement groups for the ephemeral key exchange that derives session keys. Ed25519 can appear in the certificate chain’s signatures if the certificate authority and client both support it.

Is Ed25519 or X25519 quantum-resistant?

Neither is. Both rely on the elliptic curve discrete logarithm problem, which a sufficiently powerful quantum computer running Shor’s algorithm could break. Current migration guidance, including RFC 10024 published in August 2026, pairs X25519 with the post-quantum ML-KEM algorithm in hybrid key exchange rather than replacing it outright.

Why does OpenSSH recommend Ed25519 over X25519?

SSH authentication is a signature problem. A client needs to prove it holds the private key matching a public key on the server’s authorized list, and that is Ed25519’s exact job. X25519 has no natural role in that step, though Curve25519-based key exchange does secure the SSH transport session itself.

Are Ed25519 and X25519 keys the same size?

Public keys are both 32 bytes, which is part of why they get confused. An Ed25519 private key is a 32-byte seed that expands internally to 64 bytes, and its output signature is 64 bytes, while an X25519 private key stays 32 bytes and produces a 32-byte shared secret rather than a signature.

What is the difference between Curve25519 and X25519?

Curve25519 is the name of the elliptic curve itself, introduced by Daniel Bernstein in 2006. X25519 is the specific Diffie-Hellman function built on that curve, standardized in RFC 7748. Ed25519 is a separate signature function also built on the same curve family, just using its twisted Edwards representation instead.

Is Ed25519 FIPS-approved?

Yes, as of NIST’s FIPS 186-5 revision, Ed25519 and Ed448 are approved digital signature algorithms. X25519 does not currently carry the same dedicated FIPS approval in all validated modules, which is why some regulated environments still fall back to P-256 or P-384 for key exchange even while accepting Ed25519 signatures.

Do Ed25519 and X25519 perform well on mobile and embedded devices?

Yes. Both were designed partly with constrained environments in mind, and their branch-free arithmetic runs efficiently without dedicated cryptographic hardware. That is one reason both show up so often in mobile messaging apps and IoT-adjacent protocols, where a curve like P-256 can be harder to implement safely without extra hardware acceleration.

Should I use libsodium or OpenSSL for Ed25519 and X25519?

Either is a reasonable choice for new code. libsodium exposes a simpler, higher-level API and has a long track record specifically around these two primitives, while OpenSSL 3.x offers broader protocol integration if your stack already depends on it for TLS. Pick based on what the rest of your dependency tree already uses rather than a difference in security guarantees, since both are actively maintained and widely audited.

What happens if I feed an X25519 public key into an Ed25519 verify function?

A well-written library should reject it outright, since the two key formats are not interchangeable at the API level even though both are 32 bytes. The real danger is a poorly typed integration where a generic byte array gets passed around without a type tag, letting the wrong key slip through a check that only validates length. This is exactly why type-safe APIs like Go’s crypto/ecdh package treat Ed25519 and X25519 keys as distinct, non-interchangeable types rather than raw byte slices.