Cryptography Roadmap: Classical, Symmetric, RSA, Diffie-Hellman, Elliptic Curves, Hashing, Signatures, and TLS in Python

A Python-implementation-first roadmap for cryptography, centered on key APIs (gmpy2.powmod, sympy.isprime, cryptography.hazmat, hashlib.sha256). Covers classical ciphers, symmetric keys (AES/ChaCha20), public-key cryptography (RSA/ElGamal), key exchange (Diffie-Hellman/ECDH/X25519), elliptic curves, hashing, digital signatures, and TLS-level protocols. Binary exponentiation and primality testing form the shared computational backbone across four learning levels.

Why Bundle All of “Cryptography” into a Single Hub?

GA4 shows https://yuhi-sa.github.io/en/posts/20260225_rsa/1/ jumping from 16 to 52 page views (+968%) in just seven days, with the spike continuing. The search-term breakdown shows that readers are not coming for RSA alone: they search for “RSA Python implementation,” “how public-key crypto works,” “ECDSA signature,” “Diffie–Hellman key exchange,” and “SHA-256 Python.” In other words, demand is for the full crypto stack, not a single algorithm. This is the signal that cryptography on this blog has matured into an eighth independent cluster, distinct from the signal-processing, ML, and optimization tracks.

The challenge is that cryptography mixes four axes — mathematical foundations, algorithms, protocols, and implementation libraries — and it is hard to know where to start by reading single-topic articles in isolation. This hub organizes those four axes into eight stages: classical ciphers → symmetric keys → public-key crypto → key exchange → elliptic curves → hashing → signatures → protocols.

Three existing articles on this blog form the core:

  1. https://yuhi-sa.github.io/en/posts/20260225_rsa/1/ — RSA public-key cryptography (key generation, encryption, decryption, correctness proof, Miller–Rabin primality test)
  2. https://yuhi-sa.github.io/en/posts/20201220_binary/1/ — Fast modular exponentiation via the binary method (square-and-multiply)
  3. https://yuhi-sa.github.io/en/posts/20201223_elgamal/1/ — Elliptic-curve ElGamal encryption (public-key crypto based on the discrete logarithm problem)

Around this core, we place Diffie–Hellman https://yuhi-sa.github.io/en/posts/20230907_dh/1/, its in-depth companion https://yuhi-sa.github.io/en/posts/20260614_diffie_hellman/1/ (safe primes, MITM defenses, ECDH, X25519, Triple-DH), the extended Euclidean algorithm https://yuhi-sa.github.io/en/posts/20201015_euclidean/1/, OAuth 2.0 / OIDC https://yuhi-sa.github.io/en/posts/20260226_oauth2_oidc/1/, Zero Trust https://yuhi-sa.github.io/en/posts/20260226_zero_trust/1/, and the security-certification comparison https://yuhi-sa.github.io/en/posts/20260223_security_certs/1/. The result is a single picture covering theory → implementation → protocols → operations.

We treat this as a cluster independent of the seven existing DSP/ML hubs, but binary exponentiation shares numerical foundations with both the discrete DSP basics hub https://yuhi-sa.github.io/en/posts/20260613_discrete_dsp_basics/1/ and the Monte Carlo optimization hub https://yuhi-sa.github.io/en/posts/20260522_monte_carlo_optimization/1/. These bridges are spelled out in §9.

1. Learning Roadmap by Level

Cryptography requires both mathematical rigor and fluency with implementation libraries. Here are four tracks depending on where you start.

Level 1 — Complete beginner (first contact with cryptography)

Goal: grasp the big picture that “encryption and decryption use keys that can be the same (symmetric) or different (asymmetric)” and pick up vocabulary like Caesar cipher, XOR cipher, and SHA-256.

  1. https://yuhi-sa.github.io/en/posts/20201220_binary/1/ — Get comfortable with modular exponentiation on large numbers. It is the computational core of RSA, DH, and ElGamal
  2. https://yuhi-sa.github.io/en/posts/20201015_euclidean/1/ — Learn to compute modular inverses with the Euclidean algorithm and its extended form
  3. https://yuhi-sa.github.io/en/posts/20260225_rsa/1/ — Run textbook RSA key generation, encryption, and decryption in Python
  4. https://yuhi-sa.github.io/en/posts/20260703_aes_symmetric_crypto/1/ — AES / ChaCha20 symmetric encryption: the “bulk data” half of hybrid encryption, plus how to use AEAD correctly
  5. https://yuhi-sa.github.io/en/posts/20260223_security_certs/1/ — Overview of CISSP and Japan’s Registered Information Security Specialist, where cryptography is on the syllabus

Estimated time: 2–4 weeks. You clear Level 1 once you realize that pow(m, e, n) is literally one line of RSA encryption.

Level 2 — Number theory foundations (modular arithmetic, primality, discrete log)

Goal: internalize Fermat’s little theorem, Euler’s theorem, the extended Euclidean algorithm, the Miller–Rabin primality test, and the discrete logarithm problem as your working vocabulary.

  1. https://yuhi-sa.github.io/en/posts/20260225_rsa/1/ — Euler totient \(\varphi(N) = (p-1)(q-1)\) , Miller–Rabin
  2. https://yuhi-sa.github.io/en/posts/20201015_euclidean/1/ — Extended Euclidean algorithm → modular inverse
  3. https://yuhi-sa.github.io/en/posts/20230907_dh/1/ — Diffie–Hellman key exchange, hardness of the discrete log problem (DLP)
  4. https://yuhi-sa.github.io/en/posts/20260614_diffie_hellman/1/ — Deep dive: safe primes, MITM defenses, ECDH, X25519, Triple-DH
  5. https://yuhi-sa.github.io/en/posts/20201223_elgamal/1/ — Elliptic-curve discrete log problem (ECDLP)

Estimated time: 4–6 weeks. You should be able to answer in one sentence “why is RSA secure if integer factoring is hard?” and “why is DH secure if discrete log is hard?”

Level 3 — Real understanding of public-key cryptography (RSA, ElGamal, ECC)

Goal: articulate the differences among the three families of public-key hardness assumptions — integer factoring / discrete log / elliptic-curve discrete log — and the key-length-vs-speed trade-offs.

  1. https://yuhi-sa.github.io/en/posts/20260225_rsa/1/ — RSA key sizes 2048–4096 bits, the \(e = 65537\) convention
  2. https://yuhi-sa.github.io/en/posts/20230907_dh/1/ — DH key sizes 2048–3072 bits, choice of group and generator
  3. https://yuhi-sa.github.io/en/posts/20260614_diffie_hellman/1/ — Safe primes, ECDH on Curve25519, X25519, the Signal protocol’s Triple-DH
  4. https://yuhi-sa.github.io/en/posts/20260702_elliptic_curve_cryptography/1/ — Elliptic curve cryptography in depth: point addition, ECDLP, ECDH, ECDSA, X25519 in Python
  5. https://yuhi-sa.github.io/en/posts/20201223_elgamal/1/ — Elliptic-curve ElGamal: 256 bits is comparable to RSA-3072
  6. https://yuhi-sa.github.io/en/posts/20260226_oauth2_oidc/1/ — RS256 / ES256 in real-world JWT signing

Estimated time: 6–8 weeks. You should be able to read the API tree of cryptography.hazmat.primitives.asymmetric.

Level 4 — Protocol/implementation focus (TLS, JWT, Zero Trust)

Goal: move from consumer to builder — treat cryptographic primitives as parts of larger modern protocols like TLS 1.3, JWT, OAuth 2.0, OIDC, and Zero Trust.

  1. https://yuhi-sa.github.io/en/posts/20260226_oauth2_oidc/1/ — OAuth 2.0 / OIDC and JWT signature verification
  2. https://yuhi-sa.github.io/en/posts/20260226_zero_trust/1/ — Zero Trust, mTLS, PKI
  3. https://yuhi-sa.github.io/en/posts/20260223_security_certs/1/ — Exam scope of CISSP / Japan’s Registered Information Security Specialist

Estimated time: 8–12 weeks in parallel. By the end you can fluently use cryptography.hazmat and write your own signature-verification and key-exchange handshakes.

2. Eight Stages: Classical → Symmetric → Public Key → Key Exchange → ECC → Hash → Signature → Protocol

The history of cryptography and the natural learning order line up. Here is the map.

Stage 1: Classical ciphers (Caesar, substitution, Vigenère)

Substitution and transposition ciphers with tiny key spaces; broken by frequency analysis. The educational value is grasping the abstraction “encryption = applying a key-parameterized function.”

Stage 2: Symmetric encryption (AES, ChaCha20)

Sender and receiver share the same key. AES-128 / 256 (block cipher) and ChaCha20 (stream cipher) dominate today. In Python use cryptography.hazmat.primitives.ciphers. The key-distribution problem motivates combining symmetric crypto with public-key crypto or key exchange. For the full treatment — round structure (SubBytes / ShiftRows / MixColumns / AddRoundKey), GF(2^8) math, ECB/CBC/CTR/GCM modes, nonce-reuse attacks, the ChaCha20-Poly1305 comparison, and Python implementations (AESGCM and from-scratch AES-128) — see https://yuhi-sa.github.io/en/posts/20260703_aes_symmetric_crypto/1/.

Stage 3: Public-key encryption (RSA, ElGamal)

Public and private keys differ. RSA relies on the hardness of integer factoring; ElGamal on the discrete log. See https://yuhi-sa.github.io/en/posts/20260225_rsa/1/ and https://yuhi-sa.github.io/en/posts/20201223_elgamal/1/. The computational core is binary exponentiation https://yuhi-sa.github.io/en/posts/20201220_binary/1/ and modular inverse via the extended Euclidean algorithm https://yuhi-sa.github.io/en/posts/20201015_euclidean/1/.

Stage 4: Key exchange (Diffie–Hellman, ECDH)

Two parties on a public channel derive a shared secret even if an eavesdropper sees all traffic. Security rests on the discrete log problem. The introduction is https://yuhi-sa.github.io/en/posts/20230907_dh/1/; for the production-grade details (safe primes, MITM, ECDH, X25519) read https://yuhi-sa.github.io/en/posts/20260614_diffie_hellman/1/. ECDHE is mandatory in TLS 1.3.

Stage 5: Elliptic-curve cryptography (ECC, ECDSA, ECDH)

Replace the multiplicative group of integers with the additive group of points on an elliptic curve, achieving the same security with much shorter keys. The Weierstrass form, point addition, ECDLP, the P-256 / secp256k1 / Curve25519 comparison, and Python implementations (from scratch plus cryptography.hazmat) are covered in depth in https://yuhi-sa.github.io/en/posts/20260702_elliptic_curve_cryptography/1/. Elliptic-curve ElGamal is in https://yuhi-sa.github.io/en/posts/20201223_elgamal/1/. The signature variant is ECDSA, the key-exchange variant is ECDH.

Stage 6: Hash functions (SHA-2, SHA-3, BLAKE2)

One-way functions that compress arbitrary-length input to fixed-length output. They must satisfy collision resistance, preimage resistance, and second-preimage resistance. Python provides hashlib.sha256 and hashlib.blake2b. Essential as a building block for signatures and password storage.

Stage 7: Digital signatures (RSA-PSS, ECDSA, EdDSA)

Sign with the private key, verify with the public key to provide message integrity and sender authentication simultaneously. In practice we sign the hash of the message rather than the message itself (the hash-then-sign paradigm). In Python use cryptography.hazmat.primitives.asymmetric.padding.PSS and ec.ECDSA. The math and Python implementations of RSA-PSS, ECDSA, and EdDSA are covered in depth in https://yuhi-sa.github.io/en/posts/20260704_digital_signature/1/.

Stage 8: Protocols (TLS, JWT, OAuth, PKI)

The layer where the building blocks come together into a secure session. TLS 1.3 is the full suite: ECDHE for key exchange, AES-GCM for symmetric encryption, ECDSA / EdDSA for signatures, SHA-256 for hashing. For a full walkthrough including the handshake’s HKDF key derivation, see https://yuhi-sa.github.io/en/posts/20260715_tls13_handshake/1/; for applied protocols move on to https://yuhi-sa.github.io/en/posts/20260226_oauth2_oidc/1/ and https://yuhi-sa.github.io/en/posts/20260226_zero_trust/1/.

3. Map of Constituent Articles on This Blog

A one-page view of the core articles this hub bundles and where each one sits.

Core articles (theory + implementation)

  • https://yuhi-sa.github.io/en/posts/20201220_binary/1/ — Binary exponentiation. The computational core of RSA, DH, and ElGamal
  • https://yuhi-sa.github.io/en/posts/20201015_euclidean/1/ — Euclidean / extended Euclidean algorithm. Modular inverse → RSA’s private key \(d\)
  • https://yuhi-sa.github.io/en/posts/20260703_aes_symmetric_crypto/1/ — AES / ChaCha20 symmetric encryption: rounds / GF(2^8) / ECB-to-GCM modes / AEAD / nonces
  • https://yuhi-sa.github.io/en/posts/20260225_rsa/1/ — RSA key generation, encryption, decryption, Miller–Rabin, \(e = 65537\)
  • https://yuhi-sa.github.io/en/posts/20230907_dh/1/ — Diffie–Hellman key exchange (introduction), groups and generators, DLP hardness
  • https://yuhi-sa.github.io/en/posts/20260614_diffie_hellman/1/ — Diffie–Hellman in depth: safe primes, MITM defenses, ECDH, X25519, Triple-DH
  • https://yuhi-sa.github.io/en/posts/20260702_elliptic_curve_cryptography/1/ — Elliptic curve cryptography in depth: Weierstrass form, point addition, ECDLP, ECDH, ECDSA, X25519
  • https://yuhi-sa.github.io/en/posts/20260704_digital_signature/1/ — Digital signatures in depth: RSA-PSS, ECDSA, EdDSA, hash-then-sign, nonce-reuse attacks
  • https://yuhi-sa.github.io/en/posts/20201223_elgamal/1/ — Elliptic-curve ElGamal, ECDLP, point addition
  • https://yuhi-sa.github.io/en/posts/20260223_security_certs/1/ — Comparison of security certifications whose syllabus includes cryptography

Connected destinations (protocols and operations)

  • https://yuhi-sa.github.io/en/posts/20260226_oauth2_oidc/1/ — OAuth 2.0 / OpenID Connect, JWT signatures (RS256 / ES256)
  • https://yuhi-sa.github.io/en/posts/20260226_zero_trust/1/ — Zero Trust, mTLS, PKI

Future placeholder articles

This hub is meant to be a living map. The following are high-priority candidates for future articles:

  • SHA-2 and HMAC (hashing and MAC) → published: https://yuhi-sa.github.io/en/posts/20260715_sha256_hmac/1/ (SHA-3 / BLAKE2 remain future work)
  • RSA-PSS / ECDSA / EdDSA (signature schemes) → published: https://yuhi-sa.github.io/en/posts/20260704_digital_signature/1/
  • TLS 1.3 handshake deep dive → published: https://yuhi-sa.github.io/en/posts/20260715_tls13_handshake/1/
  • Post-quantum cryptography (CRYSTALS-Kyber / Dilithium) → published: https://yuhi-sa.github.io/en/posts/20260715_post_quantum_lwe/1/

We will splice links back into this hub as each article ships.

4. Bridging the Mathematical Foundations

Four mathematical foundations recur throughout cryptography.

4.1 Modular arithmetic

The world of integers modulo \(n\) , \(\mathbb{Z}/n\mathbb{Z}\) . RSA’s \(c = m^e \bmod N\) and DH’s \(g^a \bmod p\) both live here. Binary exponentiation https://yuhi-sa.github.io/en/posts/20201220_binary/1/ computes \(m^e \bmod N\) in \(O(\log e)\) , which is what makes cryptography computationally practical.

\[ m^e \bmod N \quad\text{is } O(e) \text{ naively, but } O(\log e) \text{ with square-and-multiply.} \tag{1} \]

4.2 Primality testing and prime generation

RSA needs two large primes. Deterministic tests like AKS are too slow, so we use the probabilistic Miller–Rabin test. With \(k = 20\) rounds the false-positive probability is below \(4^{-20} \approx 10^{-12}\) . See https://yuhi-sa.github.io/en/posts/20260225_rsa/1/. In Python sympy.isprime is the standard go-to.

4.3 Discrete log (DLP) and elliptic-curve discrete log (ECDLP)

Given \(g, h \in (\mathbb{Z}/p\mathbb{Z})^*\) , find \(x\) such that \(h = g^x \bmod p\) — this is the DLP. Classically it can only be solved in sub-exponential time (general number field sieve), and this is what backs DH and ElGamal. On elliptic curves the best general attacks are fully exponential, so much shorter keys suffice for the same security. See https://yuhi-sa.github.io/en/posts/20260614_diffie_hellman/1/ for safe-prime details.

4.4 Euler’s theorem and CRT

When \(\gcd(a, N) = 1\) ,

\[ a^{\varphi(N)} \equiv 1 \pmod{N}. \tag{2} \]

This is Euler’s theorem; from it the RSA decryption identity \(c^d = m^{ed} \equiv m \pmod N\) falls out. In practice the Chinese Remainder Theorem (CRT) is used to compute modulo \(p\) and \(q\) separately and combine results, giving roughly a 4× speedup. Derivation in https://yuhi-sa.github.io/en/posts/20260225_rsa/1/.

4.5 Shared foundation: reuse of modular exponentiation

Binary exponentiation appears not only in cryptography but also in Miller–Rabin primality testing, the divide-and-conquer structure of FFT in discrete DSP (https://yuhi-sa.github.io/en/posts/20260613_discrete_dsp_basics/1/ — \(O(N \log N)\) shares the same binary-tree idea), and the binary search in cumulative-distribution sampling for Monte Carlo work (https://yuhi-sa.github.io/en/posts/20260522_monte_carlo_optimization/1/). The common idea is “expand the exponent in binary and combine sub-results.”

5. Python Implementation Guide — When to Use Which Library

In cryptography you do not reinvent the wheel. The rule is roll your own only for learning; ship with audited libraries. Here is a comparison of Python crypto libraries.

5.1 Library comparison

LibraryMain purposeKey APIsLearning vs productionNotes
Built-in powModular exponentiation \(m^e \bmod n\)pow(m, e, n)BothInternally uses binary exponentiation. Core of RSA and DH
Built-in math.gcdGreatest common divisormath.gcd(a, b)BothFast C implementation
hashlib (stdlib)Hashing and HMAChashlib.sha256(b).hexdigest(), hashlib.blake2bBothSHA-2 / SHA-3 / BLAKE2 / shake
hmac (stdlib)Message authentication codehmac.new(key, msg, hashlib.sha256).digest()BothKeyed hashing
secrets (stdlib)Cryptographic randomnesssecrets.token_bytes(32), secrets.randbelow(n)ProductionNever use random for keys or nonces
sympyPrimality testing and number theorysympy.isprime(n), sympy.nextprime(n), sympy.gcdex(a, b)LearningPerfect for textbook RSA prototypes
gmpy2Fast multi-precision arithmeticgmpy2.powmod(m, e, n), gmpy2.invert(e, phi), gmpy2.gcdextBothGMP binding. Several times faster than pow
cryptography.hazmatLow-level cryptographic primitivespadding.OAEP, padding.PSS, ec.ECDSA, CipherProductionUse this in real systems. hazmat means “hazardous materials”
cryptography.fernetSimple symmetric encryptionFernet(key).encrypt(b), .decrypt(c)ProductionAES-128-CBC + HMAC-SHA256 wrapper. Hard to misuse
PyCryptodomeAssorted crypto primitivesCrypto.PublicKey.RSA, Crypto.Cipher.AESBothOlder than cryptography. Common in tutorials
pyjwtJWT signing and verificationjwt.encode(payload, key, algorithm="RS256")ProductionEssential for OAuth / OIDC
pyca/nacl (PyNaCl)NaCl / libsodiumnacl.public.Box, nacl.signing.SigningKeyProductionCurve25519 / Ed25519. Designed to be hard to misuse

5.2 Practical guidelines

  • Learning and prototyping: sympy.isprime, pow(m, e, n), hand-written extended_gcd — implement RSA from scratch following https://yuhi-sa.github.io/en/posts/20260225_rsa/1/
  • Big-number speed: switch to gmpy2.powmod, gmpy2.invert, gmpy2.is_prime. RSA-4096 key generation gets several times faster
  • Production: use only cryptography.hazmat.primitives.asymmetric.rsa, ec, ed25519, hashes, ciphers. Never ship a hand-rolled RSA
  • Tokens: pyjwt for JWT, fernet for simple symmetric encryption. Both are hard to misuse
  • Random numbers: for keys and nonces, always use secrets or os.urandom. Never use the random module for cryptographic purposes

5.3 RSA written four ways

# 1) Pure standard library (educational)
import secrets, math
def egcd(a, b):
    if a == 0: return b, 0, 1
    g, x1, y1 = egcd(b % a, a)
    return g, y1 - (b // a) * x1, x1
# pow(m, e, n) for encryption, pow(c, d, n) for decryption

# 2) sympy (prototype)
from sympy import isprime, nextprime, mod_inverse
p = nextprime(secrets.randbits(1024))
q = nextprime(secrets.randbits(1024))
n, phi = p * q, (p - 1) * (q - 1)
e = 65537
d = mod_inverse(e, phi)

# 3) gmpy2 (fast)
import gmpy2
c = gmpy2.powmod(m, e, n)
m_dec = gmpy2.powmod(c, d, n)

# 4) cryptography.hazmat (production)
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes
key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
ct = key.public_key().encrypt(
    b"hello",
    padding.OAEP(mgf=padding.MGF1(hashes.SHA256()), algorithm=hashes.SHA256(), label=None),
)

Reading https://yuhi-sa.github.io/en/posts/20260225_rsa/1/ and https://yuhi-sa.github.io/en/posts/20201220_binary/1/ together makes it obvious why pow(m, e, n) is enough — the bridge from theory to API becomes a one-liner.

5.4 Minimal hashing and signing code

import hashlib, hmac
digest = hashlib.sha256(b"message").hexdigest()
mac = hmac.new(key=b"k", msg=b"m", digestmod=hashlib.sha256).hexdigest()

from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import hashes
sk = ec.generate_private_key(ec.SECP256R1())
sig = sk.sign(b"msg", ec.ECDSA(hashes.SHA256()))
sk.public_key().verify(sig, b"msg", ec.ECDSA(hashes.SHA256()))

6. Key Length vs Security Level

Security level (bits)RSA / DHECCSymmetricHashUse case
801024160(none)SHA-1 (retired)Legacy only
11220482243DES (retired)SHA-224Acceptable until ~2030
1283072256AES-128SHA-256Current standard
1927680384AES-192SHA-384High security
25615360512AES-256SHA-512Government top secret

How to read the table: each row lists key lengths that provide “equivalent” security. As of 2026, RSA-3072 ≈ ECC-256 ≈ AES-128 ≈ SHA-256 is the mainstream level. The ECC compression advantage is immediately visible.

For the detailed discussion of RSA-2048 vs 4096 see https://yuhi-sa.github.io/en/posts/20260225_rsa/1/, and for the ECC advantage see https://yuhi-sa.github.io/en/posts/20201223_elgamal/1/.

7. Twelve-Item Learning Checklist

Self-diagnose your understanding of the cryptography stack with these twelve items.

Modular arithmetic and algorithms

  1. Explain how binary exponentiation computes \(m^e \bmod n\) in \(O(\log e)\) time (https://yuhi-sa.github.io/en/posts/20201220_binary/1/)
  2. Derive the private \(d\) satisfying \(e \cdot d \equiv 1 \pmod{\varphi(N)}\) via the extended Euclidean algorithm (https://yuhi-sa.github.io/en/posts/20201015_euclidean/1/)
  3. State the probabilistic guarantees of the Miller–Rabin primality test in one sentence (https://yuhi-sa.github.io/en/posts/20260225_rsa/1/)

Public-key encryption and key exchange

  1. Explain that RSA’s security relies on the hardness of integer factoring
  2. Explain that DH’s security relies on the discrete log problem (https://yuhi-sa.github.io/en/posts/20230907_dh/1/)
  3. State the mathematical difference between ElGamal and RSA (DLP vs factoring) (https://yuhi-sa.github.io/en/posts/20201223_elgamal/1/)

Elliptic curves, hashing, and signatures

  1. Explain in one sentence why ECC needs shorter keys than RSA (hardness of ECDLP) (https://yuhi-sa.github.io/en/posts/20260614_diffie_hellman/1/)
  2. List the three security properties of a hash function (collision, preimage, second-preimage resistance)
  3. Explain why we sign the hash, not the message itself (the hash-then-sign paradigm)

Protocols and operations

  1. Identify the cryptographic primitives used in a TLS 1.3 handshake (ECDHE / AES-GCM / ECDSA / SHA-256) in one line
  2. Distinguish RS256 / ES256 / HS256 in the JWT alg header (https://yuhi-sa.github.io/en/posts/20260226_oauth2_oidc/1/)
  3. Explain why “do not roll your own AES or RSA” is the rule (side-channel and padding attacks) (https://yuhi-sa.github.io/en/posts/20260226_zero_trust/1/)

8. Common Stumbling Blocks — Q&A

Q1. Why is RSA slow?

RSA computes modular exponentiation over multi-precision integers of 2048–4096 bits, making it hundreds to thousands of times slower than symmetric ciphers like AES. In practice we use a hybrid scheme: RSA encrypts an AES key, AES encrypts the bulk message. TLS works this way. The symmetric side of the hybrid (AES-GCM / ChaCha20-Poly1305) is covered in https://yuhi-sa.github.io/en/posts/20260703_aes_symmetric_crypto/1/. Inside pow(m, e, n) the algorithm is binary exponentiation https://yuhi-sa.github.io/en/posts/20201220_binary/1/.

Q2. What exactly is the hardness of the discrete log problem?

Given \(g, h, p\) , find \(x\) such that \(h \equiv g^x \pmod p\) . The forward direction \(g^x\) is fast via binary exponentiation (\(O(\log x)\) ), but the inverse takes sub-exponential time \(\exp(O((\log p)^{1/3} (\log \log p)^{2/3}))\) even with the general number field sieve. That asymmetry is what gives DH its security. Details in https://yuhi-sa.github.io/en/posts/20230907_dh/1/ and https://yuhi-sa.github.io/en/posts/20260614_diffie_hellman/1/.

Q3. Why does elliptic-curve crypto get away with shorter keys?

The multiplicative group \((\mathbb{Z}/p\mathbb{Z})^*\) admits sub-exponential attacks (general number field sieve), but no analogous algorithm has been found for general elliptic curves. The best generic attacks (Pollard rho, etc.) are fully exponential \(O(\sqrt{n})\) , so smaller \(n\) still keeps security high. A 256-bit elliptic curve matches RSA-3072. See https://yuhi-sa.github.io/en/posts/20201223_elgamal/1/.

Q4. Why is “textbook RSA” dangerous as-is?

Padding-less \(c = m^e \bmod n\) is deterministic (same plaintext → same ciphertext) and vulnerable to chosen-plaintext / chosen-ciphertext attacks, including the Bleichenbacher attack. Production always pairs RSA with randomized padding — OAEP for encryption and PSS for signatures. The implementation lives in cryptography.hazmat.primitives.asymmetric.padding.OAEP. See the “Security Considerations” section of https://yuhi-sa.github.io/en/posts/20260225_rsa/1/.

Q5. Why use secrets / os.urandom instead of random?

The random module uses Mersenne Twister, a PRNG whose internal state is recoverable from past outputs — catastrophic for keys and nonces. secrets taps the OS entropy source (/dev/urandom) directly and is cryptographically safe. Use secrets.token_bytes(32) for key and token generation.

Q6. Hashing vs encryption — what is the difference?

Hashing is a one-way function (no inverse). Encryption is reversible with the key (the holder of the private key can recover the plaintext). Use hashing to check identity or as a building block for signatures; use encryption to keep data confidential. For password storage do not use SHA-256 — use bcrypt / scrypt / Argon2 to increase the computational cost and thwart brute force.

Q7. When should I migrate to post-quantum cryptography (PQC)?

NIST standardized CRYSTALS-Kyber (key exchange) and Dilithium (signatures) in 2024; they are the current mainstream choices. Because of “harvest now, decrypt later” attacks — adversaries storing today’s traffic to decrypt with a future quantum computer — any communication that must remain confidential long term should migrate to PQC sooner rather than later. A concrete migration strategy will be covered later under https://yuhi-sa.github.io/en/posts/20260226_zero_trust/1/.

This hub stands as an independent crypto cluster, but it shares mathematical bridges with the signal-processing, optimization, and ML hubs through binary exponentiation and the role of randomness.

A. Discrete DSP basics hub — shared numerical foundations

The FFT in https://yuhi-sa.github.io/en/posts/20260613_discrete_dsp_basics/1/ has the divide-and-conquer structure \(O(N \log N)\) , mathematically sibling to binary exponentiation https://yuhi-sa.github.io/en/posts/20201220_binary/1/, which “expands the exponent in binary and combines sub-results.” The common idea — using a binary-tree decomposition to bring complexity from \(O(N)\) down to \(O(\log N)\) — runs through both.

B. Monte Carlo optimization hub — contrasting notions of randomness

Sampling in https://yuhi-sa.github.io/en/posts/20260522_monte_carlo_optimization/1/ is fine with statistical pseudo-random numbers (np.random), but cryptographic key generation requires secrets / os.urandom. The meaning of “quality” for random numbers changes with context, and seeing both side by side makes the API design choices much clearer. Q&A Q5 mentioned the same distinction with MCMC (https://yuhi-sa.github.io/en/posts/20260226_mcmc/1/).

C. DSP/ML meta-roadmap — the top-level entry point

https://yuhi-sa.github.io/en/posts/20260528_dsp_ml_roadmap/1/ is the meta-roadmap that ties together the seven DSP/ML hubs. Cryptography is on a separate track, but the meta-principle — “a roadmap is engineered as a series of stages” — is shared, and this article is the eighth hub on the meta-roadmap.

D. Distance from the other hubs

HubMathematical linkLearning-order relation
https://yuhi-sa.github.io/en/posts/20260521_bode_plot/1/Weak (continuous control)Separate track
https://yuhi-sa.github.io/en/posts/20260522_filter_design_guide/1/Weak (signal processing)Separate track
https://yuhi-sa.github.io/en/posts/20260524_time_frequency_guide/1/WeakSeparate track
https://yuhi-sa.github.io/en/posts/20260525_ml_timeseries_guide/1/Medium (feature engineering)Separate track but ML in common
https://yuhi-sa.github.io/en/posts/20260613_discrete_dsp_basics/1/Strong (FFT vs square-and-multiply)Shared computational foundation
https://yuhi-sa.github.io/en/posts/20260522_monte_carlo_optimization/1/Medium (randomness quality)Complementary
https://yuhi-sa.github.io/en/posts/20260528_dsp_ml_roadmap/1/MetaHigher-level hub

Core articles bundled by this hub

  • https://yuhi-sa.github.io/en/posts/20201220_binary/1/ — Binary exponentiation
  • https://yuhi-sa.github.io/en/posts/20201015_euclidean/1/ — Euclidean / extended Euclidean algorithm
  • https://yuhi-sa.github.io/en/posts/20260703_aes_symmetric_crypto/1/ — AES / ChaCha20 symmetric encryption
  • https://yuhi-sa.github.io/en/posts/20260225_rsa/1/ — RSA public-key cryptography
  • https://yuhi-sa.github.io/en/posts/20230907_dh/1/ — Diffie–Hellman key exchange (intro)
  • https://yuhi-sa.github.io/en/posts/20260614_diffie_hellman/1/ — Diffie–Hellman deep dive
  • https://yuhi-sa.github.io/en/posts/20201223_elgamal/1/ — Elliptic-curve ElGamal
  • https://yuhi-sa.github.io/en/posts/20260226_oauth2_oidc/1/ — OAuth 2.0 / OIDC
  • https://yuhi-sa.github.io/en/posts/20260226_zero_trust/1/ — Zero Trust
  • https://yuhi-sa.github.io/en/posts/20260223_security_certs/1/ — Security certification comparison

Connected hubs

  • https://yuhi-sa.github.io/en/posts/20260521_bode_plot/1/ — Bode plot hub
  • https://yuhi-sa.github.io/en/posts/20260522_filter_design_guide/1/ — Filter-design guide hub
  • https://yuhi-sa.github.io/en/posts/20260522_monte_carlo_optimization/1/ — Monte Carlo optimization hub
  • https://yuhi-sa.github.io/en/posts/20260524_time_frequency_guide/1/ — Time-frequency analysis hub
  • https://yuhi-sa.github.io/en/posts/20260525_ml_timeseries_guide/1/ — Machine-learning time-series hub
  • https://yuhi-sa.github.io/en/posts/20260613_discrete_dsp_basics/1/ — Discrete DSP basics hub
  • https://yuhi-sa.github.io/en/posts/20260528_dsp_ml_roadmap/1/ — DSP/ML meta-roadmap

10. Comparing Hardness Assumptions — Where Security Comes From, and What Breaks It

Every algorithm covered so far falls under the single word “cryptography,” but the source of its security differs completely from algorithm to algorithm. Laying that difference out side by side is exactly the kind of value a hub article can add that individual deep dives cannot.

10.1 Hardness assumptions at a glance

AlgorithmHardness assumptionCategoryBest classical attack costImpact of a quantum computer (Shor)Details
RSAInteger factoring of a large composite \(N = pq\)Number-theoretic assumptionSub-exponential (General Number Field Sieve, GNFS)Broken in polynomial time (keys become void)https://yuhi-sa.github.io/en/posts/20260225_rsa/1/
DH / ElGamal (finite field)Discrete Logarithm Problem (DLP): find \(x\) in \(h = g^x \bmod p\)Number-theoretic assumptionSub-exponential (GNFS-family)Broken in polynomial time (keys become void)https://yuhi-sa.github.io/en/posts/20230907_dh/1/, https://yuhi-sa.github.io/en/posts/20201223_elgamal/1/
ECDH / ECDSA / EC-ElGamalElliptic-Curve Discrete Log Problem (ECDLP)Number-theoretic assumptionFully exponential (Pollard’s rho, \(O(\sqrt{n})\) )Broken in polynomial time (Shor’s algorithm extends to ECDLP too)https://yuhi-sa.github.io/en/posts/20260702_elliptic_curve_cryptography/1/
AESNone (no reduction proof): empirical resistance to differential/linear cryptanalysisCryptanalytic resistance (heuristic)Brute force \(O(2^n)\) (\(n\) = key length)Only Grover’s quadratic speedup (effective key length halves)https://yuhi-sa.github.io/en/posts/20260703_aes_symmetric_crypto/1/
SHA-256 and other hash functionsNone (no reduction proof): empirical resistance to collision/preimage searchCryptanalytic resistance (heuristic)Preimage search \(O(2^n)\) , collision search \(O(2^{n/2})\) (birthday bound)Grover halves the preimage-search exponenthttps://yuhi-sa.github.io/en/posts/20260715_sha256_hmac/1/
LWE-based (ML-KEM / ML-DSA)Learning With Errors (LWE): reduces to worst-case lattice problemsLattice-based assumptionLattice basis reduction (e.g. BKZ), roughly exponential in the lattice dimensionNo known polynomial-time algorithmhttps://yuhi-sa.github.io/en/posts/20260715_post_quantum_lwe/1/

10.2 “Hardness-assumption” crypto vs. “cryptanalytic-resistance” crypto

RSA, DH, and ECC are designed around a concrete reduction: “if this number-theoretic problem is solvable, the cryptosystem is broken.” Their security rests on specific, decades-old open problems in mathematics — integer factoring and the discrete log problem.

AES and SHA-256 have no such reduction to a well-defined mathematical hardness problem. Their SPN structure and nonlinear transforms over \(\mathrm{GF}(2^8)\) (see https://yuhi-sa.github.io/en/posts/20260703_aes_symmetric_crypto/1/) have simply resisted every known attack technique — differential cryptanalysis, linear cryptanalysis, and the rest — for a quarter century of scrutiny by the cryptanalysis community. This is not a weaker form of security; it is security by track record rather than by reduction, and it is simply a different kind of guarantee than RSA/DH/ECC provide.

10.3 The asymmetric impact of quantum computers (Shor’s algorithm)

Shor’s algorithm solves integer factoring and the discrete log problem (both over finite fields and over elliptic curves) in polynomial time on a quantum computer. This means RSA, DH, ECDH, ECDSA, and EC-ElGamal all become breakable in principle once a large enough quantum computer exists. As https://yuhi-sa.github.io/en/posts/20260715_post_quantum_lwe/1/ explains in depth, this is exactly why the migration to LWE-based post-quantum cryptography is underway.

The impact on symmetric ciphers and hash functions is asymmetrically mild. Grover’s algorithm only accelerates unstructured search quadratically, so AES-128’s effective key strength drops to 64 bits (AES-256 drops to 128 bits) — see https://yuhi-sa.github.io/en/posts/20260703_aes_symmetric_crypto/1/. 128-bit effective security is still comfortably within the current baseline (the table in §6), so the guidance is “choose AES-256 if you’re planning for the quantum era,” not “replace symmetric crypto entirely.”

No known efficient quantum algorithm analogous to Shor’s exists for the LWE problem. Lattice basis reduction (BKZ and similar) is estimated to cost roughly exponentially in the lattice dimension for both classical and quantum adversaries — this is the basis for ML-KEM/ML-DSA’s claim to being “post-quantum.”

11. Execution Verification — Measured Benchmarks of the Major Algorithms

The theoretical differences in hardness assumptions show up clearly in real execution time too. Using the cryptography library (v49.0.0, Python 3.14.6, Apple M1, macOS), we actually ran RSA, ECDSA, Ed25519, AES-GCM, and X25519 and compared them. All numbers below are measured on this machine; for operations involving random key generation we report the median over repeated trials.

11.1 Measured key generation, signing, and verification

Measured comparison of key generation / sign / verify time for RSA vs. ECDSA vs. Ed25519 (log-scale grouped bar chart). X-axis groups: Key generation / Sign / Verify. Y-axis: time in ms, log scale. Four series compared: RSA-2048 (blue), RSA-3072 (green), ECDSA P-256 (violet), Ed25519 (orange). Key generation shows RSA roughly 1,000-10,000x slower than the ECC-family; signing shows RSA more than an order of magnitude slower; verification shows the opposite, with RSA fastest thanks to its small public exponent.

AlgorithmKey generation (median)Sign (median)Verify (median)
RSA-204874.90 ms (n=20)1.067 ms (n=200)0.0333 ms (n=200)
RSA-3072176.9 ms (n=10)2.633 ms (n=200)0.0559 ms (n=200)
ECDSA P-2560.0173 ms (n=200)0.0256 ms (n=500)0.0613 ms (n=500)
Ed255190.0904 ms (n=500)0.0908 ms (n=500)0.1994 ms (n=500)

Three observations stand out.

  1. Key-generation cost directly reflects the difference in number-theoretic assumption. RSA has to repeat Miller–Rabin trials to find two large primes, making it roughly 4,300x slower for RSA-2048 and 10,200x slower for RSA-3072 than ECDSA/Ed25519 key generation (which just picks one random scalar). Our own https://yuhi-sa.github.io/en/posts/20260225_rsa/1/ measured a pure-Python implementation (no optimized library) taking a median of 9,726.6 ms to generate a 1024-bit key; by comparison, the cryptography library (GMP-class multi-precision arithmetic plus a C implementation) generates a larger 2048-bit key in 74.90 ms — over 100x faster. This is a direct, measured confirmation of the “learning implementation vs. production library” speed gap discussed in §5.
  2. RSA has an asymmetry: fast to verify, slow to sign. Modular exponentiation with the public exponent \(e = 65537\) (only 2 set bits in binary) needs about 17 squarings, while the private exponent \(d\) is a random value spanning the full 2048 bits, requiring about 2048 squarings. That asymmetry shows up as roughly a 32x gap between RSA-2048 verify (0.033 ms) and sign (1.067 ms). ECDSA and Ed25519 have no such asymmetry — signing and verifying cost about the same.
  3. ECDSA and Ed25519 are comparable, but Ed25519 verification is slightly slower. This comes from Ed25519 verification requiring a double scalar multiplication (checking \([s]B = R + [h]A\) ) — a single-verification cost, distinct from the batch-verification optimization that https://yuhi-sa.github.io/en/posts/20260704_digital_signature/1/ highlights as one of Ed25519’s design strengths.

11.2 Measured symmetric throughput and key-exchange cost

Measured comparison of AES-GCM throughput and key-establishment cost (two-panel bar chart). Left panel: AES-128-GCM vs. AES-256-GCM encryption throughput on a 64 MiB payload (MB/s). Right panel: per-session cost (ms) of X25519 ECDH vs. RSA-2048 and RSA-3072 key transport.

AES-128-GCM vs. AES-256-GCM bulk-encryption throughput (64 MiB payload, median of 5 runs):

Key lengthThroughput
AES-1287,355.4 MB/s
AES-2566,168.6 MB/s

AES-256 has 14 rounds versus AES-128’s 10, so a naive expectation would be 40% slower — but the measured gap is only about 16%. AES-NI hardware acceleration of the round function absorbs most of the extra cost, confirming empirically that the cost of “choosing AES-256 for the quantum era” (§10.3) is close to negligible.

Per-session cost of establishing a shared secret (RSA rows exclude key generation, assuming a long-term key reused across sessions; the X25519 row includes both sides’ key generation, since ephemeral X25519 keys are realistically generated fresh every session):

SchemePer-session cost
X25519 (ECDH, both sides, full exchange including keygen)0.501 ms (n=300)
RSA-2048 key transport (OAEP encrypt + decrypt, excluding keygen)1.063 ms (n=100)
RSA-3072 key transport (OAEP encrypt + decrypt, excluding keygen)2.693 ms (n=100)

X25519 is about 2.1x faster than RSA-2048 key transport and about 5.4x faster than RSA-3072. On top of that, RSA key transport requires the server to hold onto a long-lived RSA keypair (generated once, but at a cost of 75–190 ms per §11.1), whereas X25519 key generation itself costs only 0.017–0.09 ms (the same order as ECDSA P-256 key generation) — cheap enough that using a fresh (ephemeral) key every session carries essentially zero practical cost. This is one concrete reason TLS 1.3 mandates ECDHE and retired static RSA key transport: it delivers the forward secrecy that https://yuhi-sa.github.io/en/posts/20260614_diffie_hellman/1/ discusses at essentially zero marginal cost.

12. Which Algorithm for Which Use Case — A Decision Tree

Combining the theory and the measurements above, here is guidance for five use cases that come up constantly in practice.

Use caseRecommendationWhyDetails
TLS handshake key exchangeECDHE (X25519)Per §11.2, fast and essentially free to generate, so it can be single-use every session for forward secrecy. Static RSA key transport is discouragedhttps://yuhi-sa.github.io/en/posts/20260715_tls13_handshake/1/
Data-at-rest encryptionAES-256-GCM (ChaCha20-Poly1305 on mobile/embedded)Symmetric crypto is orders of magnitude faster than RSA/ECC (§11.2). 256 bits gives ample margin against both brute force and Grover’s algorithmhttps://yuhi-sa.github.io/en/posts/20260703_aes_symmetric_crypto/1/
Digital signatures (new systems)Ed25519 (ECDSA P-256 for interop needs, RSA-PSS for legacy)Deterministic signing eliminates the nonce-reuse failure class, and key generation/sign/verify are all fast (§11.1)https://yuhi-sa.github.io/en/posts/20260704_digital_signature/1/
Password storagebcrypt / scrypt / Argon2 (never SHA-256 directly)See §12.1 below(Not covered elsewhere on this blog — summarized below)
Long-term confidentiality (harvest-now, decrypt-later)Hybrid key exchange (X25519 + ML-KEM-768, etc.)AND-composition design: secure as long as either the classical or the PQC leg holds. Deployed in major browsers per RFC 9954https://yuhi-sa.github.io/en/posts/20260715_tls13_handshake/1/, https://yuhi-sa.github.io/en/posts/20260715_post_quantum_lwe/1/

12.1 Why you must not use SHA-256 for password storage

The articles this hub bundles cover RSA, DH, ECC, AES, hashing, signatures, and TLS — but none of them cover password storage, deliberately. It deserves a brief, correct explanation here, including why.

A hash function like SHA-256 derives its security from one-wayness — fast to compute forward, hard to invert (Stage 6 above). But that very “fast to compute” property becomes a liability for password hashing. If an attacker obtains a leaked password hash, all they need to do is run SHA-256 over a dictionary or brute-force candidate list and compare. Modern GPUs/ASICs can compute SHA-256 billions of times per second, so most common passwords fall within seconds to minutes.

bcrypt, scrypt, and Argon2 solve this by making the hash computation deliberately slow and memory-intensive. bcrypt repeatedly applies the Blowfish key schedule with a tunable cost parameter; scrypt and Argon2 (winner of the 2015 Password Hashing Competition) go further by requiring large amounts of memory access (memory-hardness), which sharply degrades the cost-effectiveness of parallel GPU/ASIC attacks. All three build in a per-user salt by design, which also neutralizes rainbow-table attacks. “Hash function security = one-wayness” and “password-hash security = deliberate slowness” are different requirements — conflating them is a common and dangerous mistake.

13. Recent Developments — Current Status of NIST PQC Standardization

As https://yuhi-sa.github.io/en/posts/20260715_post_quantum_lwe/1/ details, NIST finalized FIPS 203 (ML-KEM, key encapsulation), FIPS 204 (ML-DSA, signatures), and FIPS 205 (SLH-DSA, hash-based signatures) in August 2024. In March 2025, NIST went on to select HQC (Hamming Quasi-Cyclic) — based on a different mathematical structure (error-correcting codes) than lattice problems — as a fifth PQC algorithm, serving as a backup for ML-KEM; a draft standard is expected around 2026, with final standardization targeted for 2027 ( NIST News, March 11, 2025 ).

As an update at the time of writing: in August 2025, NIST submitted a public draft of the lattice-based signature scheme FN-DSA (formerly FALCON) as FIPS 206. Its main advantage over ML-DSA (Dilithium) is a smaller signature size; the review period is expected to run about a year, as with the other PQC standards, so final standardization is likely in late 2026 to early 2027 ( DigiCert, “Quantum-Ready FN-DSA (FIPS 206) Nears Draft Approval from NIST” ; NIST CSRC, FIPS 206 presentation ). Major certificate authorities have stated they will not deploy FN-DSA in production until the standard is finalized, so the practical choice today remains the ML-KEM (key exchange) + ML-DSA or SLH-DSA (signatures) combination.

Cryptography is a stack of mathematics, algorithms, libraries, and protocols. Use this hub as the base camp and head into whichever level matches your interest and goals.