Avatar
Part time CTF Player learn every day!!
🌠 I Love Hoshimachi Suisei!! 🌠
🌠 I Love Hoshimachi Suisei!! 🌠

Practical Cryptography for Devs & CTFers: Concepts, Pitfalls, Tools, and Krypton-Inspired Labs

Practical Cryptography for Devs & CTFers

Halloo SuiiKawaii dessu! Cryptography topic today so the main reason Cryptography invented is for protects confidentiality, integrity, and authenticity. This post is hands-on yet academically grounded: you’ll build the right mental models, learn modern primitives, understand formal properties (IND-CPA/CCA, UF-CMA), avoid the classic foot-guns, and practice through Krypton-style mini labs.

Sui

If you plan to tackle Krypton, see my series hub: OverTheWire Krypton Overview.

Table of Contents


1) Threat model & mental model

Threat model checklist (data lifecycle):

  • At rest: disks, backups → envelope encryption (DEK wrapped by KEK), access controls, audit logs.
  • In transit: client ↔ server → TLS 1.3 (ECDHE + AEAD).
  • In use: process memory → minimize plaintext exposure; consider streaming APIs, TEE when justified.

Mental model:

  • Encrypt for confidentiality.
  • MAC/sign for integrity + authenticity.
  • Bind context (headers, filenames, version) via AEAD AAD.
  • Ensure freshness (nonces, counters), and key separation (HKDF).

Further references:


2) Encoding vs encryption vs hashing vs signing

ThingReversible?Keys?Security goalExamples
EncodingYesNoRepresentationBase64, Hex, URL
EncryptionYesYesConfidentialityAES-GCM, ChaCha20-Poly1305
HashNoNoFingerprintSHA-256, SHA-3
MACNoYes (shared)Integrity+authHMAC-SHA256
SignatureVerifiablePriv/PublicIntegrity+authEd25519, RSA-PSS

Further references:


3) Classical ciphers (Krypton warm-up)

Why they matter: build intuition for frequency analysis, key length discovery, and layer peeling (vibe of Krypton).

  • Caesar/ROT:
    echo "URYYB JBEYQ" | tr 'A-Z' 'N-ZA-M'   # ROT13
    
  • Affine E(x)=(a·x + b) mod 26, gcd(a,26)=1 → brute a,b is tiny.
  • Vigenère → Kasiski/Friedman → per-slice frequency.
  • Transposition → permute columns/rails; look for n-gram anomalies.

Further references:


4) Symmetric crypto: AES/ChaCha, modes, AEAD, SIV

Modes (intuition):

  • ECB: reveals patterns → never for data.
  • CBC: legacy; IV must be random; padding-oracle risks.
  • CTR: stream; never reuse nonce+key.
  • GCM: AEAD (confidentiality + integrity) with 96-bit unique nonces.
  • AES-SIV: misuse-resistant AEAD if nonce uniqueness can’t be guaranteed.

AEAD & AAD: bind context (headers, filenames, protocol version) so swaps are detected.

# AES-256-GCM demo
openssl enc -aes-256-gcm -salt -pbkdf2 \
  -in secret.txt -out secret.bin \
  -pass pass:'CorrectHorseBatteryStaple'

openssl enc -d -aes-256-gcm -pbkdf2 \
  -in secret.bin -out secret.txt \
  -pass pass:'CorrectHorseBatteryStaple'

Further references:


5) Asymmetric crypto: RSA/ECC, KEX, hybrid

  • RSA: use OAEP (encryption) and PSS (signatures). Never raw RSA.
  • ECC: X25519 (key exchange), Ed25519 (signatures) are excellent defaults.
  • Hybrid (envelope): generate random AEAD key → encrypt data; wrap the AEAD key with RSA/ECC.
# GPG mini-demo (hybrid under the hood)
gpg --full-generate-key
gpg --armor --export your@email
gpg --encrypt --armor -r their@email file.txt
gpg --decrypt file.txt.asc

Further references:


6) Hashes, MACs, HKDF, password KDFs

  • Hash: SHA-256/512, SHA-3; avoid MD5/SHA-1.
  • MAC: HMAC-SHA256 when not using AEAD.
  • HKDF: derive independent subkeys from one secret (info label per use).
  • Passwords: Argon2id (tune memory/time/parallelism), or scrypt/bcrypt; always unique salt.
# Fingerprint
openssl dgst -sha256 my.iso

# Argon2id (if argon2 CLI is available)
echo -n "p@ssw0rd" | argon2 somesalt -id -t 3 -m 16 -p 1

Further references:


7) Randomness, IVs/nonces, salts

  • Use CSPRNG (OS RNG, language crypto APIs). Don’t invent RNGs.
  • Nonces: never reuse with same key (GCM/CTR/ChaCha20-Poly1305). For untrusted counters, consider AES-SIV.
  • Salts: public & unique → defeat precomputation (rainbow tables).
openssl rand -hex 32

Further references:


8) Signatures, PKI, and TLS 1.3 mental model

  • Signatures (UF-CMA): Ed25519 or RSA-PSS.
  • PKI: CAs sign X.509 certs; clients verify chain, names, usage.
  • TLS 1.3: ECDHE (FS) → authenticate server via cert → AEAD for data.

Further references:


9) Provable security (IND-CPA/CCA, UF-CMA) & composition

  • IND-CPA: indistinguishable under chosen-plaintext attack (semantic secrecy).
  • IND-CCA2: resists adaptive chosen-ciphertext queries (decryption oracle).
  • UF-CMA: unforgeability under chosen-message attack (signatures).
  • Composition: Prefer AEAD or Encrypt-then-MAC; derive separate keys via HKDF labels.

Further references:


10) Side-channels & implementation hygiene

  • Constant-time operations; avoid secret-dependent branches/array indices.
  • Beware padding oracles; unify error messages and timing.
  • Microarchitectural leaks (cache timing, branch prediction) → rely on vetted libs.
  • File formats: authenticate headers/metadata via AAD; version fields.
  • JWT gotchas: pin algorithms; strong keys; prefer EdDSA; validate claims/exp/aud.

Further references:


11) Key management & ops (envelope, rotation, KMS)

  • Envelope: data encrypted by DEK; DEK wrapped by KEK (KMS/HSM).
  • Rotation: schedule KEK rotation; re-wrap DEKs; rotate AEAD nonces per key.
  • Access: least privilege; audit logs; detect anomalies.
  • Secrets hygiene: avoid hard-coded keys; secret scanning in CI; commit signing.

Further references:


12) Tools & recipes (OpenSSL, GPG, CyberChef)

OpenSSL

# Random 32B key (hex)
openssl rand -hex 32

# SHA-256 digest (hex)
openssl dgst -sha256 file.bin

# RSA keypair (use OAEP/PSS in protocols, not raw RSA)
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out rsa.pem
openssl rsa -in rsa.pem -pubout -out rsa.pub

GPG (hybrid)

gpg --full-generate-key
gpg --armor --export your@email
gpg --encrypt --armor -r their@email file.txt
gpg --decrypt file.txt.asc

CyberChef: build pipelines (Base64 → Hex → XOR → ROT) for Krypton-style peeling.

Further references:


13) Python mini-cookbook (cryptography)

Install first: pip install cryptography

AES-GCM (AEAD)

from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from os import urandom

key = AESGCM.generate_key(bit_length=256)   # 32 bytes
aesgcm = AESGCM(key)
nonce = urandom(12)                         # 96-bit unique per encryption
aad = b"header"
pt  = b"secret message"

ct = aesgcm.encrypt(nonce, pt, aad)         # ciphertext || tag
pt2 = aesgcm.decrypt(nonce, ct, aad)        # raises if tag invalid
assert pt2 == pt

HKDF (derive labeled subkeys)

from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from cryptography.hazmat.primitives import hashes
from os import urandom

ikm  = urandom(32)
salt = urandom(16)

enc_key = HKDF(algorithm=hashes.SHA256(), length=32, salt=salt, info=b"enc").derive(ikm)
mac_key = HKDF(algorithm=hashes.SHA256(), length=32, salt=salt, info=b"mac").derive(ikm)

Ed25519 signatures

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

sk = Ed25519PrivateKey.generate()
pk = sk.public_key()

msg = b"sign me"
sig = sk.sign(msg)
pk.verify(sig, msg)   # raises if invalid

X25519 key agreement + AEAD

from cryptography.hazmat.primitives.asymmetric import x25519
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from os import urandom

a_priv, b_priv = x25519.X25519PrivateKey.generate(), x25519.X25519PrivateKey.generate()
a_pub, b_pub   = a_priv.public_key(), b_priv.public_key()

a_shared = a_priv.exchange(b_pub)
b_shared = b_priv.exchange(a_pub)
assert a_shared == b_shared

key = HKDF(hashes.SHA256(), 32, salt=urandom(16), info=b"x25519-aead").derive(a_shared)
aes = AESGCM(key)
nonce = urandom(12)
ct = aes.encrypt(nonce, b"psst", b"aad")
pt = aes.decrypt(nonce, ct, b"aad")

Note: Store nonces with ciphertext; ensure per-key nonce uniqueness (or use AES-SIV for misuse-resistance).


14) Krypton-inspired mini labs

Lab A — Encoding stack Hex → Base64 → Gunzip.

xxd -r -p msg.hex > msg.bin
base64 -d msg.b64 > msg.gz
file msg.gz && gunzip msg.gz

Lab B — ROT/Vigenère intuition Write a small Caesar brute and eyeball plausible English.

Lab C — AEAD integrity Flip a byte in AES-GCM ciphertext → decryption should fail.

echo "hello" > p.txt
openssl enc -aes-256-gcm -salt -pbkdf2 -in p.txt -out c.bin -pass pass:pw
printf '\x00' | dd of=c.bin bs=1 seek=10 count=1 conv=notrunc 2>/dev/null
openssl enc -d -aes-256-gcm -pbkdf2 -in c.bin -out x.txt -pass pass:pw || echo "tamper detected"

Lab D — Hash & KDF Try Argon2id with different memory/time; chart time vs settings.


15) Verification harness (inline, copy & run)

These tiny harnesses let you prove the properties above.

Shell harness (OpenSSL) — AES-GCM, tamper detection, SHA-256 ```bash #!/usr/bin/env bash # crypto_verification_harness.sh # Quick checks for AES-GCM, tamper detection, and SHA-256. # Usage: bash crypto_verification_harness.sh set -euo pipefail workdir="$(mktemp -d)" trap 'rm -rf "$workdir"' EXIT echo "[*] Working dir: $workdir" cd "$workdir" # 1) Prepare plaintext echo "hello cryptography" > p.txt # 2) AES-256-GCM encrypt/decrypt with OpenSSL echo "[*] AES-GCM encrypt..." openssl enc -aes-256-gcm -salt -pbkdf2 -in p.txt -out c.bin -pass pass:'pw' >/dev/null 2>&1 echo "[*] AES-GCM decrypt..." openssl enc -d -aes-256-gcm -pbkdf2 -in c.bin -out d.txt -pass pass:'pw' >/dev/null 2>&1 if diff -q p.txt d.txt >/dev/null; then echo "[+] Decryption matches original (confidentiality OK)" else echo "[-] Decrypted text differs!" ; exit 1 fi # 3) Tamper detection echo "[*] Tamper ciphertext byte and expect failure..." printf '\x00' | dd of=c.bin bs=1 seek=10 count=1 conv=notrunc 2>/dev/null if openssl enc -d -aes-256-gcm -pbkdf2 -in c.bin -out t.txt -pass pass:'pw' >/dev/null 2>&1; then echo "[-] Decryption succeeded after tamper (unexpected)!" ; exit 1 else echo "[+] Tamper detected (integrity OK)" fi # 4) SHA-256 digest echo "[*] SHA-256 of plaintext:" openssl dgst -sha256 p.txt echo "[*] Done." ```
Python harness — AES-GCM, HKDF, Ed25519 (cryptography) ```python #!/usr/bin/env python3 # crypto_verification_harness.py # Tests AES-GCM, HKDF, Ed25519 using the 'cryptography' library. # Usage: python3 crypto_verification_harness.py import os, sys try: from cryptography.hazmat.primitives.ciphers.aead import AESGCM from cryptography.hazmat.primitives.kdf.hkdf import HKDF from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey except Exception as e: print("[!] Missing dependency 'cryptography'. Install via: pip install cryptography") sys.exit(1) def test_aes_gcm(): key = AESGCM.generate_key(bit_length=256) aes = AESGCM(key) nonce = os.urandom(12) aad = b"header" pt = b"secret message" ct = aes.encrypt(nonce, pt, aad) pt2 = aes.decrypt(nonce, ct, aad) assert pt2 == pt # tamper tampered = bytearray(ct) tampered[5] ^= 0xFF try: aes.decrypt(nonce, bytes(tampered), aad) raise AssertionError("Tamper not detected") except Exception: pass print("[+] AES-GCM OK (encrypt/decrypt + tamper detection)") def test_hkdf(): ikm = os.urandom(32) salt = os.urandom(16) info = b"example-subkey" kdf = HKDF(algorithm=hashes.SHA256(), length=32, salt=salt, info=info) k1 = kdf.derive(ikm) kdf2 = HKDF(algorithm=hashes.SHA256(), length=32, salt=salt, info=info) k2 = kdf2.derive(ikm) assert k1 == k2 print("[+] HKDF OK (deterministic for same inputs)") def test_ed25519(): sk = Ed25519PrivateKey.generate() pk = sk.public_key() msg = b"sign me" sig = sk.sign(msg) pk.verify(sig, msg) print("[+] Ed25519 OK (sign/verify)") def main(): test_aes_gcm() test_hkdf() test_ed25519() print("[*] All tests passed.") if __name__ == "__main__": main() ```

Cheatsheet (algorithms & sizes)

PurposeRecommendedNotes
Symmetric AEADAES-GCM (128/256), ChaCha20-Poly1305, AES-SIVPrefer AEAD; SIV for misuse-resistance.
SignaturesEd25519, RSA-PSS (2048+), ECDSA P-256Ed25519: simple & robust.
Key exchangeX25519, ECDH P-256Use ephemeral keys for FS.
HashSHA-256/512, SHA-3-256Avoid MD5/SHA-1.
HKDFHKDF-SHA256Separate labels per key use.
Password KDFArgon2id, scrypt/bcryptUnique salt; tune cost.
Nonce sizeGCM: 96-bitMust be unique per key.
RSA size2048/3072 bitsPrefer ECC for new designs.

Printable 1-page cheatsheet (PNG + PDF)

![Crypto Cheatsheet](/assets/images/crypto/crypto_cheatsheet.png)

[Download the PDF version](/assets/downloads/crypto/crypto_cheatsheet.pdf)


Further reading & references

Video primers (curated)

Books & formal

  • Serious Cryptography — Aumasson
  • Cryptography Engineering — Ferguson, Schneier, Kohno
  • Introduction to Modern Cryptography — Katz & Lindell

Standards & specs

  • RFC 8446 (TLS 1.3) • RFC 5869 (HKDF) • RFC 7748 (X25519) • RFC 8032 (Ed25519) • RFC 5116 (AEAD)
  • NIST SP 800-38D (GCM) • NIST SP 800-56A (ECC key establishment) • NIST SP 800-90 (DRBGs)

Thanks for reading!

Until next time — Otsumachi!! 💖☄️✨

Cinema

all tags

GOT-overwrite aboutme aead ai alphanumeric-shellcode apt argc0 argon2 aslr assembly asymmetric atoi automation backbox bandit base64 bash beginner behemoth binary binary-exploitation binary-to-ascii blackarch blind blind-sqli blogging blue-team bruteforce buffer-overflow buffer-overwrite c caesar canary capabilities checksec command-injection commonmark cookie cron crypto cryptography ctf cutter cyberchef cybersecurity defenders detection dev directory-traversal dnf docs drifter ecc education elf env envp exploitation finale forensics format-string formulaone frequency frequency-analysis gcc gdb getchar gfm ghidra github-pages governance gpg guide hashing hkdf http jekyll jmpbuf kali kasiski kdf kernel keylength kramdown krypton lab ld_preload leviathan lfi lfsr linux linux-syscall llmops log-poisoning ltrace manpage markdown maze memcpy mitigations mitmproxy mlops narnia natas networking newline-injection nonce nop-sled nx object-injection obsidian openssl osint overflow overthewire package-manager pacman parrot path path-hijacking pathname php pie pkc pki pointer-trick pqc priv-esc privilege-escalation provable-security pwn pwntools pyshark python race-condition radare2 rag randomness recon red-team redirect relro requests ret2env ret2libc reverse-engineering reversing ricing roadmap rop rot13 rsa scapy security seed seo serialization session setjmp-longjmp setuid shell shellcode smoke soc sockets sprintf sql-injection srop stack-canary stack-overflow strace strcmp strcpy streamcipher strings strncpy strtoul substitution suid suisei symlink symmetric terminal test threat-intel time-based tls troubleshooting tshark type-juggling ubuntu udp utumno vigenere virtualbox virtualization vmware vortex walkthrough web windows wireshark writing wsl x86
dash theme for Jekyll by bitbrain made with