iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Elliptic Curve / Ed25519

Elliptic curve cryptography gets the same security as RSA at a fraction of the key size: a 256-bit ECDSA key matches roughly a 3072-bit RSA key. That makes ECC the default for TLS, SSH, JWT signing, and any new key-exchange protocol. The two curves to know are Curve25519 (Ed25519 for signing, X25519 for ECDH) and NIST P-256.

Ed25519 sign/verify and X25519 key exchange

EXAMPLE
from cryptography.hazmat.primitives.asymmetric.ed25519 import (
    Ed25519PrivateKey, Ed25519PublicKey,
)
from cryptography.hazmat.primitives.asymmetric.x25519 import (
    X25519PrivateKey, X25519PublicKey,
)
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from cryptography.exceptions import InvalidSignature

# ============================================================
# 1) Ed25519 — fast, deterministic signatures (the default today)
# ============================================================
sk = Ed25519PrivateKey.generate()
pk = sk.public_key()

message = b'order=12345, total=4995, paid=true'
sig = sk.sign(message)                       # 64-byte signature, no hash arg
print('signature length:', len(sig), 'bytes')

try:
    pk.verify(sig, message)
    print('verified')
except InvalidSignature:
    print('tampered or wrong key')

# Serialise keys for storage/transport
sk_pem = sk.private_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PrivateFormat.PKCS8,
    encryption_algorithm=serialization.NoEncryption(),
)
pk_pem = pk.public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo,
)

# ============================================================
# 2) X25519 — Diffie–Hellman key exchange
# ============================================================
alice_sk = X25519PrivateKey.generate()
bob_sk   = X25519PrivateKey.generate()

# Each side computes the shared secret from THEIR private + OTHER public
alice_shared = alice_sk.exchange(bob_sk.public_key())
bob_shared   = bob_sk.exchange(alice_sk.public_key())
assert alice_shared == bob_shared
print('raw shared secret:', alice_shared.hex()[:32], '...')

# Always run the raw secret through a KDF before using it as a key
session_key = HKDF(
    algorithm=hashes.SHA256(),
    length=32,
    salt=None,
    info=b'app=shop-api v1 session',
).derive(alice_shared)
print('session key:', session_key.hex())

# ============================================================
# 3) Curve choice cheat sheet
# ============================================================
# Signing:  prefer Ed25519. ECDSA-P256 only when you must interop (JWT ES256, etc.).
# DH:       prefer X25519. ECDH-P256 only for interop.
# Avoid:    NIST P-192 (too small), Brainpool (limited library support), custom curves.

Why it matters

Ed25519 signing is deterministic — the same key + message always produces the same signature. That removes a whole class of nonce-reuse bugs that have repeatedly broken ECDSA implementations (PlayStation 3, early Bitcoin wallets). Default to Ed25519 unless a protocol forces ECDSA on you.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// Elliptic curves: same security at smaller key sizes.
// Ed25519 for signatures; X25519 for ECDH key exchange.
const { generateKeyPairSync } = require('crypto');
const { privateKey, publicKey } = generateKeyPairSync('ed25519');
Try it Yourself »

Exercise

Modern EC signature scheme.

generateKeyPairSync(' ')

Discussion

Loading…