Skillversitas

Elliptic Curve Cryptography

Elliptic curve cryptography reaches the same security as RSA or Diffie-Hellman with far smaller keys: an ECDSA-P256 signature matches a 3072-bit RSA signature, and an X25519 key exchange matches 3072-bit DH, at a fraction of the size and compute cost. That is why curves are the default in TLS 1.3, SSH, and mobile protocols, and why the cryptography library treats them as first-class citizens.

Standard Curves

CurveTypeSecurityTypical use
SECP256R1 (P-256)NIST, Weierstrass~128 bitscertificates, ECDSA, TLS
SECP384R1 (P-384)NIST~192 bitslong-lived high-value keys
X25519Montgomery~128 bitskey exchange (ECDHE)
Ed25519twisted Edwards~128 bitssignatures (SSH, TLS 1.3)

P-256 is the universal interoperability choice; Ed25519/X25519 are the speed and safety favorites for new systems (deterministic signatures, no padding pitfalls).

Generating EC Keys

from cryptography.hazmat.primitives.asymmetric import ec

# key exchange
x25519 = ec.generate_private_key(ec.X25519())

# signing / certificates
p256 = ec.generate_private_key(ec.SECP256R1())
ed = ec.generate_private_key(ec.Ed25519())

print(p256.curve.name)     # 'secp256r1'
print(ed.public_key())     # Ed25519PublicKey

ECDSA Signatures

from cryptography.hazmat.primitives.asymmetric import ec, utils
from cryptography.hazmat.primitives import hashes

signature = p256.sign(
    b"release-2.4.1 manifest",
    ec.ECDSA(hashes.SHA256()),
)

p256.public_key().verify(signature, b"release-2.4.1 manifest",
                        ec.ECDSA(hashes.SHA256()))

ECDSA signatures are variable-length DER blobs by default; the utils.Prehashed and SIG_ENCODE helpers produce the fixed 64-byte form (r || s) used by many protocols.

Ed25519 Signatures

signature = ed.sign(b"payload")
ed.public_key().verify(signature, b"payload")   # no hash argument - it hashes internally

Ed25519 is simpler to use correctly: no padding parameter, deterministic signatures, and a fixed 64-byte output. SSH keys, TLS 1.3, and Git's signed commits increasingly use it.

Serializing Curve Keys

from cryptography.hazmat.primitives import serialization

pem = x25519.private_bytes(
    serialization.Encoding.PEM,
    serialization.PrivateFormat.PKCS8,
    serialization.NoEncryption(),
)
loaded = serialization.load_pem_private_key(pem, password=None)

The same PKCS#8/SPKI encodings as RSA - the curve is identified inside the key data, so tools that read "a private key" work with any of them.

Summary

Default to X25519 for key exchange, Ed25519 for new signatures, and P-256 where interoperability demands NIST curves. Small keys, fast operations, fewer padding pitfalls - curves are the right first choice in anything you design today.