- Compare symmetric and asymmetric encryption and explain the key-distribution problem
- Build RSA keys with small numbers, then encrypt, decrypt and sign
- Explain the properties of hashes and how to store passwords properly
- Recognise the main attacks and choose defences against them
When Leyla pays in her banking app, the data passes through dozens of strangers' devices, yet none of them can read or change the amount, and the bank is sure the request really came from Leyla. That is cryptography at work. It serves four goals: confidentiality (others cannot read), integrity (changes are detected), authenticity (we know who sent it) and non-repudiation (the sender cannot later say “it wasn't me”).
Symmetric encryption
- M, Cplaintext and ciphertext
- Kthe same secret key held by both sides
- E, Dencryption and decryption algorithms (e.g. AES)
Kerckhoffs's principle: the algorithm may be public; security must rest only on the secrecy of the key.
The modern standard is AES (128-, 192- or 256-bit keys): it is very fast and has hardware support in processors. A 128-bit key has 2¹²⁸ ≈ 3.4 · 10³⁸ possibilities — trying them all is practically impossible. The real problem is different: how do you share the key? Every pair among n people needs its own key — n(n − 1)/2 keys, 499,500 for 1000 users. And the key cannot be sent over an insecure channel the first time.
Asymmetric cryptography: Diffie–Hellman and RSA
In asymmetric cryptography every user has two keys: a public key given to everyone and a private key shown to no one. What is encrypted with the public key can be opened only with the private key. It rests on mathematical operations that are “easy one way, hard to reverse”: multiplying two large primes is easy, but factoring the product is very hard; computing gᵃ mod p is easy, but recovering a (the discrete logarithm) is hard.
- p, ga public prime and base
- a, bthe two sides' secret numbers
- sthe shared secret — never sent over the network
Diffie–Hellman key exchange: an eavesdropper sees p, g, A and B, but to get s must solve a discrete logarithm.
p = 23, g = 5. Aysel's secret is a = 6, Murad's is b = 15. Find the public numbers and the shared key.
Show solutionHide solution
A = 5⁶ = (5²)³ ≡ 2³ = 8.
B = 5¹⁵ = 5¹² · 5³; 5¹² = (5⁶)² ≡ 64 ≡ 18; 5³ = 125 ≡ 10; 18 · 10 = 180 ≡ 19.
Aysel: s = 19⁶; 19 ≡ −4, (−4)⁶ = 4096 = 23 · 178 + 2 → s = 2.
Murad: s = 8¹⁵ = 2⁴⁵; 2¹¹ = 2048 = 23 · 89 + 1 ≡ 1, so 2⁴⁵ = (2¹¹)⁴ · 2 ≡ 2 ✓.
Both got the same key, yet the number 2 never appeared on the network.
- p, qtwo large secret primes (≈ 1024 bits each in practice)
- (n, e)the public key
- dthe private key: the inverse of e modulo φ(n)
- m, cmessage (0 ≤ m < n) and ciphertext
RSA (Rivest, Shamir, Adleman, 1977). Finding d requires φ(n), and that requires the factors of n — security rests on how hard factoring is.
p = 3, q = 11, e = 3. Build the keys, encrypt and decrypt the message m = 4, then sign it and verify the signature.
Show solutionHide solution
d: 3d ≡ 1 (mod 20) → d = 7 (3 · 7 = 21 = 20 + 1). Public key (33, 3), private key 7.
Encryption: c = 4³ = 64 mod 33 = 31.
Decryption: 31⁷ mod 33; 31 ≡ −2 → (−2)⁷ = −128; 128 = 3 · 33 + 29 → −128 ≡ −29 ≡ 4 ✓.
Signature (with the private key): s = 4⁷ = 16,384 = 33 · 496 + 16 → s = 16.
Verification (with the public key): 16³ = 4096 = 33 · 124 + 4 → 4 = m ✓ — the signature is valid.
p, g = 23, 5
a, b = 6, 15
A, B = pow(g, a, p), pow(g, b, p)
print('DH public:', A, B, '| shared:', pow(B, a, p), pow(A, b, p))
p, q, e = 3, 11, 3
n, phi = p * q, (p - 1) * (q - 1)
d = pow(e, -1, phi)
m = 4
c = pow(m, e, n)
print('RSA n =', n, 'phi =', phi, 'd =', d)
print('encrypt', m, '->', c, '| decrypt ->', pow(c, d, n))
s = pow(m, d, n)
print('signature', s, '| verify ->', pow(s, e, n))▸ Expected output
DH public: 8 19 | shared: 2 2 RSA n = 33 phi = 20 d = 7 encrypt 4 -> 31 | decrypt -> 4 signature 16 | verify -> 4
pow(x, k, n) is fast modular exponentiation (by repeated squaring, O(log k) multiplications), and pow(e, -1, phi) finds the modular inverse with the extended Euclidean algorithm. Both examples confirm our hand calculations.Hash functions and digital signatures
A cryptographic hash (such as SHA-256) turns data of any length into a fixed-length (256-bit) “fingerprint”. Requirements: the same result every time; the data cannot be recovered from the hash (one-wayness); finding two different inputs with the same hash is practically impossible (collision resistance); a one-bit change flips about half the bits of the hash (avalanche effect). A hash is not encryption: it has no key and cannot be reversed.
import hashlib, math
for text in ['Educora', 'educora', 'Educora!']:
print(text, hashlib.sha256(text.encode()).hexdigest()[:16])
rate = 10 ** 10
for name, n, length in [('8 lowercase', 26, 8), ('12 mixed', 94, 12)]:
bits = length * math.log2(n)
seconds = n ** length / rate
print(name, '|', round(bits, 1), 'bits |', f'{seconds:.3g}', 'seconds')▸ Expected output
Educora b3dbb4d80128c71a educora 48ecb7c2aeec01dc Educora! 836636e98b18e97a 8 lowercase | 37.6 bits | 20.9 seconds 12 mixed | 78.7 bits | 4.76e+13 seconds
- Hentropy of a random password, bits
- Lpassword length
- Nalphabet size (26 lowercase letters, 94 printable characters)
Each extra bit doubles the brute-force effort. The formula holds only for truly random passwords: ones like “Baku2026!” fall quickly to dictionary attacks.
Passwords must never be stored as plain text or with plain SHA-256: the server gives each user a random salt and hashes the password with a deliberately slow function — Argon2, bcrypt, scrypt or PBKDF2. The salt stops equal passwords from producing equal hashes and defeats precomputed tables; the slowness blocks billions of fast guesses. A digital signature works like this: the sender signs the message's hash with their private key, and anyone verifies it with the sender's public key. Who a public key belongs to is confirmed by a certificate — a document signed by a trusted authority (CA).
Attacks and defences
| Attack | What happens | Defence |
|---|---|---|
| Phishing | a fake site or email steals the password | two-factor authentication, checking the address, passkeys |
| SQL injection | input text becomes part of the query | parameterised queries, ORMs |
| XSS | a script is injected into someone else's page | escaping output, Content-Security-Policy |
| Man-in-the-middle | traffic is secretly read or altered | TLS, certificate checks |
| Password guessing | brute-force and dictionary attacks | long random passwords, rate limiting, salted slow hashes |
| Ransomware | encrypts files and demands payment | offline backups, updates, least privilege |
-- the program glues user input into the query:
-- WHERE email = '<input>'
-- the attacker types: x' OR '1'='1
SELECT COUNT(*) AS leaked_rows
FROM students
WHERE email = 'x' OR '1'='1';▸ Expected output
leaked_rows 12
OR '1'='1' is always true, all 12 students leak. With a parameterised query (WHERE email = ?) the same input is compared as plain text and returns 0 rows.Key points
- Symmetric encryption (AES) is fast but has a key-distribution problem: n people need n(n − 1)/2 keys.
- Diffie–Hellman creates a shared key without sending it: s = gᵃᵇ mod p.
- RSA: n = pq, ed ≡ 1 (mod φ), c = mᵉ mod n, m = cᵈ mod n; signature s = mᵈ, verification sᵉ = m.
- A hash is one-way and collision-resistant; passwords are stored with a salt and a slow hash (Argon2, bcrypt).
- Parameterised queries stop SQL injection, TLS stops man-in-the-middle attacks; don't roll your own crypto.
Check yourself
10 questions. Every correct answer earns XP.