Authorized environments only. Run cryptographic attacks (password cracking, padding-oracle exploitation, RSA factoring of recovered keys, TLS scanning of production endpoints) against systems you own or have written authorization to test. Decrypting third-party traffic, breaking keys you do not control, or scanning hosts without permission can violate computer-fraud, wiretap, and export-control statutes. See Legal & Ethics.

Table of Contents

  1. Overview
  2. Quick Reference
  3. Mathematical Foundations
  4. Symmetric Cryptography
  5. Asymmetric Cryptography
  6. Hash Functions & Authentication
  7. Password Cracking
  8. SSL/TLS & PKI
  9. Common Attacks
  10. CTF Crypto Challenges
  11. Post-Quantum Cryptography
  12. Tools Reference
  13. Legal & Ethical Considerations

Overview

Purpose: Practical guide for cryptographic analysis, vulnerability assessment, and security research focused on real-world applications.

Scope:

  • Cryptographic algorithm analysis and exploitation
  • Password hash cracking techniques
  • SSL/TLS security assessment
  • RSA and symmetric crypto attacks
  • CTF cryptography challenges

Prerequisites:

  • Basic programming (Python recommended)
  • Command-line proficiency
  • Understanding of hexadecimal and binary

Key Philosophy:

  • Focus on practical attacks over theoretical cryptography
  • Hands-on examples for every concept
  • Real-world tools used in security research

Quick Reference

Algorithm Security Status

TypeAlgorithmKey SizeStatusNotes
SymmetricAES128/192/256-bit✅ SecureIndustry standard
ChaCha20-Poly1305256-bit✅ SecureAEAD; mobile/no-AES-NI default
3DES168-bit⚠️ DeprecatedNIST disallowed after 2023
DES/RC456-bit/Variable❌ BrokenNever use
AsymmetricRSA≥2048-bit✅ Secure (classical)3072-bit for ≥2030 (NIST SP 800-57)
RSA<2048-bit❌ WeakEasily factored
ECC (P-256, X25519, Ed25519)256-bit✅ Secure (classical)Smaller keys, same security
ML-KEM (FIPS 203)512/768/1024✅ Secure (PQ KEM)Replaces CRYSTALS-Kyber; finalized Aug 2024
ML-DSA (FIPS 204)44/65/87✅ Secure (PQ sig)Replaces CRYSTALS-Dilithium
SLH-DSA (FIPS 205)Variable✅ Secure (PQ sig)Stateless hash-based; replaces SPHINCS+
HashSHA-256/384/512256/384/512-bit✅ SecureGeneral purpose (SHA-2 family)
SHA-3 (Keccak)224/256/384/512-bit✅ SecureDifferent construction (sponge); FIPS 202
BLAKE2 / BLAKE3256-bit (default)✅ SecureFaster than SHA-2; BLAKE3 parallelizable
SHA-1160-bit❌ BrokenCollision attacks (SHAttered 2017)
MD5128-bit❌ BrokenCollisions trivial; never use for security
PasswordArgon2idVariable✅ BestPHC winner 2015; OWASP-recommended variant
scryptVariable✅ SecureMemory-hard; common in cryptocurrency
bcrypt≤72 bytes✅ SecureIndustry standard; truncates long passwords
PBKDF2-HMAC-SHA256Variable✅ AcceptableMinimum 600k iterations (OWASP 2023+)

Essential Commands

# Hash identification
hashid '$2y$10$abc123...'
echo "5d41402abc4b2a76b9719d911017c592" | hashid
 
# Password cracking
hashcat -m 0 -a 0 hashes.txt rockyou.txt           # MD5 dictionary
hashcat -m 1400 -a 0 hashes.txt rockyou.txt        # SHA-256
hashcat -m 3200 -a 0 hashes.txt rockyou.txt        # bcrypt
 
# RSA analysis/attacks (modern entry point; older python3 RsaCtfTool.py still works)
RsaCtfTool --publickey public.pem --private
openssl rsa -in private.pem -text -noout
 
# SSL/TLS testing
testssl.sh --full https://target.com
nmap --script ssl-enum-ciphers -p 443 target.com
nmap --script ssl-cert,ssl-ccs-injection -p 443 target.com
 
# Certificate inspection
openssl x509 -in cert.pem -text -noout
openssl s_client -connect target.com:443 -showcerts
 
# Encoding/Decoding
echo "SGVsbG8=" | base64 -d                        # Base64 decode
echo "48656c6c6f" | xxd -r -p                      # Hex to ASCII

Mathematical Foundations

Why Math Matters in Crypto

Purpose: Modern cryptography relies on mathematical “hard problems” - operations that are easy to compute but hard to reverse without a secret key.

Core Concepts You Need:

  • Modular arithmetic → RSA encryption/decryption
  • Prime numbers → RSA key generation
  • Greatest Common Divisor (GCD) → Finding shared prime factors between keys

Real-World Impact:

  • Weak math = broken crypto (Debian OpenSSL bug 2008, ROCA 2017)
  • Understanding math enables attacks (factoring RSA, discrete log problems)

Modular Arithmetic

What it is: “Clock arithmetic” - numbers wrap around after reaching a modulus value.

Example: 17 mod 5 = 2 (17 ÷ 5 = 3 remainder 2)

Why it’s used in crypto:

  • Operations are reversible with the correct key (modular inverse)
  • Results stay bounded (0 to n-1)
  • Foundation of RSA: c = m^e mod n (encryption), m = c^d mod n (decryption)

Python Examples:

# Basic modular operations
print((17 + 8) % 5)      # 0 (25 mod 5)
print((7 * 9) % 5)       # 3 (63 mod 5)
print(pow(2, 100, 17))   # 1 (2^100 mod 17, computed efficiently)
 
# Modular inverse (required for RSA)
def mod_inverse(a, m):
    """Find x such that (a * x) mod m = 1"""
    def extended_gcd(a, b):
        if a == 0:
            return b, 0, 1
        gcd, x1, y1 = extended_gcd(b % a, a)
        x = y1 - (b // a) * x1
        y = x1
        return gcd, x, y
 
    gcd, x, _ = extended_gcd(a, m)
    if gcd != 1:
        return None  # Inverse doesn't exist
    return (x % m + m) % m
 
# Example: 3 * 4 ≡ 1 (mod 11)
print(mod_inverse(3, 11))  # Output: 4

Prime Numbers & Factorization

What they are: Numbers divisible only by 1 and themselves (2, 3, 5, 7, 11…).

Why they’re critical:

  • RSA security depends on difficulty of factoring n = p × q (two large primes)
  • Small or predictable primes = broken RSA
  • GCD attacks reveal shared factors between multiple RSA keys

Primality Testing:

import random
 
def is_prime_miller_rabin(n, k=5):
    """Miller-Rabin primality test (probabilistic)"""
    if n < 2:
        return False
    if n == 2 or n == 3:
        return True
    if n % 2 == 0:
        return False
 
    # Write n-1 as 2^r * d
    r, d = 0, n - 1
    while d % 2 == 0:
        r += 1
        d //= 2
 
    # Witness loop
    for _ in range(k):
        a = random.randint(2, n - 2)
        x = pow(a, d, n)
 
        if x == 1 or x == n - 1:
            continue
 
        for _ in range(r - 1):
            x = pow(x, 2, n)
            if x == n - 1:
                break
        else:
            return False
 
    return True
 
print(is_prime_miller_rabin(17))  # True
print(is_prime_miller_rabin(18))  # False

GCD Attack (Finding Shared Factors):

import math
 
# Real-world scenario: Two RSA moduli share a prime factor
n1 = 143  # 11 × 13
n2 = 221  # 13 × 17
 
# GCD reveals shared prime
gcd = math.gcd(n1, n2)
print(f"Shared factor: {gcd}")  # 13
 
# Both keys are now broken!
p1 = gcd
q1 = n1 // p1
print(f"n1 = {p1} × {q1}")  # 13 × 11
 
p2 = gcd
q2 = n2 // p2
print(f"n2 = {p2} × {q2}")  # 13 × 17

Real Attack (2012): Researchers collected millions of RSA public keys and computed GCDs between pairs, finding thousands that shared prime factors!


Common Encoding Schemes

IMPORTANT: Encoding ≠ Encryption! Encoding is reversible by anyone - no security!

Base64

What it is: Encodes binary data into ASCII text (64 printable characters: A-Z, a-z, 0-9, +, /).

When used:

  • Email attachments (SMTP requires text)
  • JSON/XML with binary data
  • Embedded images in HTML: data:image/png;base64,...

How to recognize: Ends with = or == (padding), only alphanumeric + / + +

import base64
 
# Encode
encoded = base64.b64encode(b"Hello World")
print(encoded)  # b'SGVsbG8gV29ybGQ='
 
# Decode
decoded = base64.b64decode(encoded)
print(decoded)  # b'Hello World'

Hexadecimal

What it is: Represents binary using 16 symbols (0-9, A-F). 2 hex digits = 1 byte.

When used:

  • Hash outputs (MD5, SHA-256)
  • Memory addresses (0x401000)
  • Raw bytes in packet captures
# String to hex
text = "Hello"
hex_string = text.encode().hex()
print(hex_string)  # 48656c6c6f
 
# Hex to string
original = bytes.fromhex(hex_string).decode()
print(original)  # Hello

Symmetric Cryptography

AES (Advanced Encryption Standard)

Status: ✅ Secure (when used correctly)

Key Sizes: 128-bit (secure), 192-bit, 256-bit (high security)

Modes of Operation:

  • ECB (Electronic Codebook) - ❌ Never use (deterministic, patterns visible)
  • CBC (Cipher Block Chaining) - ⚠️ Requires random IV, vulnerable to padding oracle
  • CTR (Counter Mode) - ✅ Good (parallelizable, no padding)
  • GCM (Galois/Counter Mode) - ✅ Best choice (authenticated encryption)
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
 
# Encryption
key = get_random_bytes(32)      # 256-bit key
nonce = get_random_bytes(12)    # 96-bit nonce
 
cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
plaintext = b"Secret message"
ciphertext, tag = cipher.encrypt_and_digest(plaintext)
 
print(f"Key: {key.hex()}")
print(f"Nonce: {nonce.hex()}")
print(f"Ciphertext: {ciphertext.hex()}")
print(f"Tag: {tag.hex()}")
 
# Decryption
cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
decrypted = cipher.decrypt_and_verify(ciphertext, tag)
print(f"Decrypted: {decrypted}")

ECB Mode Vulnerability

Problem: Identical plaintext blocks → identical ciphertext blocks (patterns leak information)

Famous Example: ECB-encrypted Tux penguin image shows visible outline

Detection:

# Look for repeating blocks in ciphertext
xxd ciphertext.bin | sort | uniq -d
# If duplicates found → likely ECB mode

Padding Oracle Attack

Vulnerability: Application leaks whether padding is valid/invalid → decrypt ciphertext byte-by-byte

Vulnerable Code:

from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
 
def decrypt_and_check(ciphertext, iv, key):
    cipher = AES.new(key, AES.MODE_CBC, iv)
    try:
        plaintext = unpad(cipher.decrypt(ciphertext), 16)
        return True  # Valid padding
    except ValueError:
        return False  # Invalid padding ← INFORMATION LEAK!

Tool: PadBuster automates this attack

padbuster http://target.com/decrypt.php "ciphertext_hex" "iv_hex" 16 -encoding 0

Asymmetric Cryptography

RSA (Rivest-Shamir-Adleman)

How RSA Works:

  1. Choose two large primes: p, q
  2. Compute modulus: n = p × q
  3. Compute totient: φ(n) = (p-1)(q-1)
  4. Choose public exponent: e (commonly 65537)
  5. Compute private exponent: d = e^(-1) mod φ(n)

Public key: (n, e) Private key: (n, d)

Encryption: c = m^e mod n Decryption: m = c^d mod n

Generate RSA Keys

# OpenSSL
openssl genrsa -out private.pem 4096
openssl rsa -in private.pem -pubout -out public.pem
openssl rsa -in private.pem -text -noout  # View key components
from Crypto.PublicKey import RSA
 
# Generate 2048-bit key
key = RSA.generate(2048)
 
# Export keys
with open('private.pem', 'wb') as f:
    f.write(key.export_key())
 
with open('public.pem', 'wb') as f:
    f.write(key.publickey().export_key())
 
print(f"n: {key.n}")
print(f"e: {key.e}")
print(f"d: {key.d}")

RSA Attacks

1. Small Exponent Attack (e=3)

Vulnerability: If e=3 and m^3 < n, ciphertext c = m^3 (no modular reduction) → just compute cube root!

import gmpy2
 
def small_e_attack(c, e=3):
    """If m^e < n, then c = m^e → m = e-th root of c"""
    m, exact = gmpy2.iroot(c, e)
    if exact:
        return int(m)
    return None
 
# Example
c = 1030301  # Small ciphertext
m = small_e_attack(c, e=3)
if m:
    print(f"Plaintext: {m}")
    print(f"Text: {bytes.fromhex(hex(m)[2:])}")

2. Common Modulus Attack

Vulnerability: Same message encrypted with same n but different e values → recover plaintext without private key!

def common_modulus_attack(c1, c2, e1, e2, n):
    """
    If m^e1 mod n = c1 and m^e2 mod n = c2
    Can recover m using Extended Euclidean Algorithm
    """
    from math import gcd
 
    def extended_gcd(a, b):
        if a == 0:
            return b, 0, 1
        gcd, x1, y1 = extended_gcd(b % a, a)
        x = y1 - (b // a) * x1
        y = x1
        return gcd, x, y
 
    gcd_val, a, b = extended_gcd(e1, e2)
 
    if gcd_val != 1:
        return None
 
    # m = (c1^a * c2^b) mod n
    if a < 0:
        c1 = pow(c1, -1, n)
        a = -a
    if b < 0:
        c2 = pow(c2, -1, n)
        b = -b
 
    m = (pow(c1, a, n) * pow(c2, b, n)) % n
    return m

3. Fermat’s Factorization (Close Primes)

Vulnerability: If p and q are close in value, can factor n quickly

import gmpy2
 
def fermat_factor(n):
    """Factor n if p and q are close"""
    a = gmpy2.isqrt(n) + 1
 
    for _ in range(100000):
        b_squared = a * a - n
        b = gmpy2.isqrt(b_squared)
 
        if b * b == b_squared:
            p = a + b
            q = a - b
            return int(p), int(q)
 
        a += 1
 
    return None, None
 
# Example with close primes
n = 8051  # 89 × 91-1 = 89 × 90 (close primes)
p, q = fermat_factor(n)
if p and q:
    print(f"p = {p}, q = {q}")

4. Wiener’s Attack (Small Private Exponent)

Vulnerability: When d < (1/3) * n^(1/4), the private exponent can be recovered from the public key alone using continued-fraction expansion of e/n.

When to suspect: Small d chosen for fast decryption (signing devices, IoT). Often paired with very large e to keep e * d ≡ 1 (mod φ(n)) balanced.

# Conceptual; production-ready implementations: owiecc/wiener_attack, RsaCtfTool's wiener module
# Procedure: compute continued-fraction convergents of e/n; for each convergent k/d,
# test whether (e*d - 1) / k == φ(n) yields integer p, q from x^2 - (n - φ + 1)*x + n = 0

5. Boneh-Durfee Attack (Lattice-based Wiener Extension)

Vulnerability: Extends Wiener up to d < n^0.292 using Coppersmith / LLL lattice reduction. RsaCtfTool exposes this via the boneh_durfee attack module.

6. ROCA (Return of Coppersmith’s Attack, CVE-2017-15361)

Vulnerability: RSA keys generated by Infineon’s RSALib (used in TPM chips, Yubikey 4, Estonian eID, Gemalto smartcards) have a structured form n = k * M + (65537^a mod M) that allows factoring 1024-bit keys in ~97 CPU-days and 2048-bit in ~140 CPU-years (commercial-feasible for 1024).

Detection:

# roca-detect from CRoCS-MUNI
pip install roca-detect
roca-detect public_key.pem
# Or batch: roca-detect-keystore *.pem

7. Automated RSA Attacks

RsaCtfTool — Automates Wiener, Hastad, Boneh-Durfee, common modulus, Fermat, Pollard rho/p-1, Williams p+1, ECM, ROCA, SQUFOF, FactorDB lookup, Z3, Wolfram Alpha, and more.

# Install (Python 3.9+ required)
git clone https://github.com/RsaCtfTool/RsaCtfTool.git
cd RsaCtfTool
pip3 install -r requirements.txt
 
# Modern entry point (older `python3 RsaCtfTool.py` form still works)
RsaCtfTool --publickey public.pem --private
 
# Decrypt ciphertext (current flag: --decryptfile; legacy --uncipherfile retained)
RsaCtfTool --publickey public.pem --decryptfile encrypted.bin
 
# Try all attacks
RsaCtfTool --publickey public.pem --private --attack all
 
# Specific attack module
RsaCtfTool --publickey public.pem --private --attack wiener
RsaCtfTool --publickey public.pem --private --attack boneh_durfee
RsaCtfTool --publickey public.pem --private --attack roca

Hash Functions & Authentication

Hash Function Basics

Purpose: One-way function that produces fixed-size output from variable input

Properties:

  • Deterministic: Same input always produces same output
  • Fast to compute: Hashing is quick
  • Avalanche effect: Small input change = completely different hash
  • One-way: Can’t reverse hash to get original input
  • Collision-resistant: Hard to find two inputs with same hash

Common Hash Algorithms

import hashlib
 
message = b"Hello World"
 
# MD5 (128-bit) - ❌ BROKEN
md5 = hashlib.md5(message).hexdigest()
print(f"MD5: {md5}")
 
# SHA-1 (160-bit) - ❌ BROKEN (collisions exist)
sha1 = hashlib.sha1(message).hexdigest()
print(f"SHA-1: {sha1}")
 
# SHA-256 (256-bit) - ✅ SECURE
sha256 = hashlib.sha256(message).hexdigest()
print(f"SHA-256: {sha256}")
 
# SHA-512 (512-bit) - ✅ SECURE
sha512 = hashlib.sha512(message).hexdigest()
print(f"SHA-512: {sha512}")
 
# SHA-3 (Keccak, FIPS 202) - ✅ SECURE - sponge construction, immune to length extension
sha3_256 = hashlib.sha3_256(message).hexdigest()
print(f"SHA3-256: {sha3_256}")
 
# BLAKE2 - ✅ SECURE - faster than SHA-2, included in stdlib
blake2 = hashlib.blake2b(message).hexdigest()
print(f"BLAKE2b: {blake2}")
 
# BLAKE3 - ✅ SECURE - parallelizable, faster than BLAKE2 (pip install blake3)
# import blake3
# print(f"BLAKE3: {blake3.blake3(message).hexdigest()}")

HMAC (Message Authentication)

Purpose: Verify message integrity and authenticity using secret key

import hmac
import hashlib
 
key = b"secret_key"
message = b"Important message"
 
# Generate HMAC
mac = hmac.new(key, message, hashlib.sha256).hexdigest()
print(f"HMAC: {mac}")
 
# Verify HMAC (constant-time comparison prevents timing attacks)
def verify_hmac(key, message, provided_mac):
    expected_mac = hmac.new(key, message, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected_mac, provided_mac)  # ✅ Secure
 
# ❌ INSECURE: if expected_mac == provided_mac  (timing attack vulnerable)

Hash Length Extension Attack

Vulnerability: Hash functions like SHA-256 vulnerable when used as H(secret || data) instead of HMAC

Vulnerable Code:

import hashlib
 
secret = b"secret_key"
data = b"user=admin"
 
# ❌ VULNERABLE
hash_vulnerable = hashlib.sha256(secret + data).hexdigest()
 
# ✅ SECURE: Use HMAC instead
hash_secure = hmac.new(secret, data, hashlib.sha256).hexdigest()

Attack Tool:

# hash_extender - Exploits length extension (HashPump's bwall/HashPump repo is gone; this is the
# actively-recommended replacement; supports MD4/MD5/RIPEMD-160/SHA-0/SHA-1/SHA-256/SHA-512/WHIRLPOOL)
git clone https://github.com/iagox86/hash_extender.git
cd hash_extender && make
 
# Extend hash without knowing secret
./hash_extender --data 'user=guest' \
                --secret 16 \
                --append '&admin=true' \
                --signature 'original_hex_hash' \
                --format sha256
 
# SHA-3, BLAKE2, BLAKE3, and HMAC-* are NOT vulnerable to length extension
# (sponge / keyed-hash constructions). Use HMAC or migrate to SHA-3 / BLAKE2.

Password Cracking

Password Hashing

Wrong Way (Fast Hashing):

import hashlib
 
# ❌ MD5/SHA-256 too fast - vulnerable to brute force
password = "password123"
bad_hash = hashlib.sha256(password.encode()).hexdigest()

Right Way (Slow Hashing with Salt):

import bcrypt
 
# ✅ bcrypt - Slow hashing resistant to brute force
password = b"password123"
salt = bcrypt.gensalt(rounds=12)  # Work factor (higher = slower)
hashed = bcrypt.hashpw(password, salt)
 
print(f"Hash: {hashed}")
 
# Verify
if bcrypt.checkpw(password, hashed):
    print("Password correct")

Hash Identification

# hashid tool
hashid '$2y$10$abc...'
# Output: bcrypt
 
hashid '5d41402abc4b2a76b9719d911017c592'
# Output: MD5

Manual Identification:

Hash ExampleAlgorithmPattern
5d41402abc4b2a76b9719d911017c592MD532 hex chars
356a192b7913b04c54574d18c28d46e6395428abSHA-140 hex chars
a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146eSHA-25664 hex chars
abc$xyzMD5 (Unix)Starts with
102ybcryptStarts with or
abc$xyzSHA-512 (Unix)Starts with

Hashcat (GPU Password Cracking)

Common Hash Modes (full list: hashcat --help or hashcat.net wiki example_hashes):

  • 0 = MD5
  • 100 = SHA1
  • 1400 = SHA-256
  • 1700 = SHA-512
  • 3200 = bcrypt
  • 1800 = sha512crypt (Unix $6$)
  • 1000 = NTLM
  • 5500 = NetNTLMv1
  • 5600 = NetNTLMv2
  • 8900 = scrypt
  • 13400 = KeePass 1/2
  • 14600 = LUKS
  • 11600 = 7-Zip
  • 13600 = WinZip
  • 22000 = WPA-PBKDF2-PMKID+EAPOL (replaces legacy 2500/16800)
  • Argon2 modes vary by hashcat build [verify 2026-04-25] — check hashcat --help | grep -i argon on your installed version

Dictionary Attack:

# MD5
hashcat -m 0 -a 0 hashes.txt /usr/share/wordlists/rockyou.txt
 
# SHA-256
hashcat -m 1400 -a 0 hashes.txt /usr/share/wordlists/rockyou.txt
 
# bcrypt (slow)
hashcat -m 3200 -a 0 hashes.txt /usr/share/wordlists/rockyou.txt

Rule-Based Attack:

# Apply rules (password → Password1, p@ssword, etc.)
hashcat -m 0 -a 0 hashes.txt rockyou.txt -r /usr/share/hashcat/rules/best64.rule

Mask Attack (Pattern Brute Force):

# Crack 8-digit PIN
hashcat -m 0 -a 3 hashes.txt ?d?d?d?d?d?d?d?d
 
# Mask charsets:
# ?l = lowercase (a-z)
# ?u = uppercase (A-Z)
# ?d = digits (0-9)
# ?s = special chars
# ?a = all (?l?u?d?s)
 
# Pattern: "password" + 2 digits
hashcat -m 0 -a 3 hashes.txt password?d?d

Show Cracked:

hashcat -m 0 hashes.txt --show

SSL/TLS & PKI

Certificate Inspection

# View certificate details
openssl x509 -in cert.pem -text -noout
 
# Extract from server
openssl s_client -connect target.com:443 -showcerts </dev/null 2>/dev/null | \
  openssl x509 -outform PEM > cert.pem
 
# Check expiration
openssl x509 -in cert.pem -noout -dates
 
# View subject/issuer
openssl x509 -in cert.pem -noout -subject
openssl x509 -in cert.pem -noout -issuer

SSL/TLS Testing

testssl.sh (Comprehensive Scanner) — current stable: 3.2.3 (Feb 2026); 3.3dev for in-progress features.

# Clone (use --depth 1 for the stable branch only)
git clone --depth 1 https://github.com/drwetter/testssl.sh.git
 
# Full scan
./testssl.sh --full https://target.com
 
# Specific vulnerabilities
./testssl.sh --heartbleed https://target.com
./testssl.sh --poodle https://target.com
./testssl.sh --robot https://target.com
./testssl.sh --logjam https://target.com
./testssl.sh --freak https://target.com
 
# Protocol coverage (TLS 1.3 supported, including 0-RTT detection where applicable)
./testssl.sh --protocols https://target.com
 
# Cipher / KEX inspection (post-quantum hybrid groups such as X25519MLKEM768
# appear under key-exchange listings on supporting endpoints) [verify 2026-04-25]
./testssl.sh --cipher-per-proto https://target.com
./testssl.sh --groups https://target.com

Nmap SSL Scripts (all part of standard NSE distribution):

# Enumerate ciphers, protocols, and cipher preference order
nmap --script ssl-enum-ciphers -p 443 target.com
 
# Certificate inspection
nmap --script ssl-cert -p 443 target.com
 
# Heartbleed (CVE-2014-0160)
nmap --script ssl-heartbleed -p 443 target.com
 
# POODLE (CVE-2014-3566)
nmap --script ssl-poodle -p 443 target.com
 
# CCS injection (CVE-2014-0224)
nmap --script ssl-ccs-injection -p 443 target.com
 
# DH parameter check
nmap --script ssl-dh-params -p 443 target.com

Common SSL/TLS Vulnerabilities

VulnerabilityCVEImpactTest
HeartbleedCVE-2014-0160OpenSSL memory leaknmap --script ssl-heartbleed
POODLECVE-2014-3566SSLv3 padding oracletestssl.sh --poodle
BEASTCVE-2011-3389CBC vulnerability TLS 1.0testssl.sh --beast
CCS InjectionCVE-2014-0224OpenSSL key material disclosurenmap --script ssl-ccs-injection
FREAKCVE-2015-0204Export-grade RSA downgradetestssl.sh --freak
LOGJAMCVE-2015-4000DHE downgrade to 512-bittestssl.sh --logjam
DROWNCVE-2016-0800SSLv2 cross-protocol attacktestssl.sh --drown
Sweet32CVE-2016-218364-bit block cipher (3DES/Blowfish)testssl.sh --sweet32
ROBOTCVE-2017-13099 (and others)RSA PKCS#1 v1.5 Bleichenbacher oracletestssl.sh --robot
RaccoonCVE-2020-1968Static-DH timing leakcovered by --full

Common Attacks

Classical Ciphers

Caesar Cipher (ROT13)

def caesar_decrypt(ciphertext, shift):
    plaintext = ""
    for char in ciphertext:
        if char.isalpha():
            shifted = ord(char) - shift
            if char.isupper():
                if shifted < ord('A'):
                    shifted += 26
            else:
                if shifted < ord('a'):
                    shifted += 26
            plaintext += chr(shifted)
        else:
            plaintext += char
    return plaintext
 
# Brute force all shifts
ciphertext = "KHOOR ZRUOG"
for shift in range(26):
    print(f"Shift {shift}: {caesar_decrypt(ciphertext, shift)}")
# Output includes: "Shift 3: HELLO WORLD"

XOR Cipher

Single-Byte XOR

def single_byte_xor(data, key):
    return bytes([b ^ key for b in data])
 
def score_english(text):
    """Score based on English letter frequency"""
    common = b'etaoinshrdlu '
    return sum(1 for b in text.lower() if b in common)
 
# Brute force
ciphertext = bytes.fromhex("1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736")
 
best_score = 0
best_key = 0
best_text = b''
 
for key in range(256):
    plaintext = single_byte_xor(ciphertext, key)
    score = score_english(plaintext)
 
    if score > best_score:
        best_score = score
        best_key = key
        best_text = plaintext
 
print(f"Key: {best_key} ('{chr(best_key)}')")
print(f"Plaintext: {best_text}")

Repeating-Key XOR

def repeating_key_xor(data, key):
    """XOR with repeating key"""
    repeated_key = (key * (len(data) // len(key) + 1))[:len(data)]
    return bytes([d ^ k for d, k in zip(data, repeated_key)])
 
# Encrypt
plaintext = b"Secret message"
key = b"KEY"
ciphertext = repeating_key_xor(plaintext, key)
 
# Decrypt (same operation)
decrypted = repeating_key_xor(ciphertext, key)
print(decrypted)  # b"Secret message"

CTF Crypto Challenges

Common Patterns

1. RSA Challenges

# Automated approach
python3 RsaCtfTool.py --publickey public.pem --uncipherfile flag.enc
 
# Manual checks:
# - Small e (e=3) → small exponent attack
# - Small n → factor with factordb.com
# - Multiple keys → common modulus attack
# - p and q close → Fermat factorization

2. XOR Challenges

# Single-byte XOR
ciphertext = bytes.fromhex("...")
for key in range(256):
    plaintext = bytes([b ^ key for b in ciphertext])
    if b'flag{' in plaintext or b'CTF{' in plaintext:
        print(plaintext)
 
# Repeating-key XOR → use frequency analysis to find key length

3. Base64 Layers

import base64
 
# Multiple layers of encoding
encoded = "VkZoU1FtRnRjRXhsZEVGMVZHaGxiblJwWTJGMFpVRjFkR2hsYm5ScFkyRjBaVUYxZEdob..."
 
# Decode until plaintext
while True:
    try:
        decoded = base64.b64decode(encoded)
        if decoded == encoded or not decoded:
            break
        encoded = decoded
        print(f"Decoded: {decoded}")
    except:
        break
 
print(f"Final: {encoded}")

4. AES ECB Oracle

# If you can encrypt chosen plaintexts (ECB mode)
# Can decrypt unknown suffix byte-by-byte
 
def ecb_oracle_attack(encryption_oracle, block_size=16):
    """Byte-at-a-time ECB decryption"""
    known = b''
 
    for block_num in range(10):
        for byte_pos in range(block_size):
            # Craft input
            padding = b'A' * (block_size - 1 - byte_pos)
            target = encryption_oracle(padding)[:block_size * (block_num + 1)]
 
            # Try all bytes
            for byte_val in range(256):
                test_input = padding + known + bytes([byte_val])
                test_output = encryption_oracle(test_input)[:block_size * (block_num + 1)]
 
                if test_output == target:
                    known += bytes([byte_val])
                    break
            else:
                return known
 
    return known

Useful Tools & Websites

Online Tools:

Command-Line:

# CyberChef offline
git clone https://github.com/gchq/CyberChef.git
cd CyberChef && firefox CyberChef.html

Post-Quantum Cryptography

Status (as of 2026)

NIST finalized the first three FIPS post-quantum standards in August 2024. Migration is no longer hypothetical — federal systems and major TLS deployments have begun rolling out hybrid (classical + PQ) algorithms.

StandardAlgorithmOrigin SubmissionUse Case
FIPS 203ML-KEM (512 / 768 / 1024)CRYSTALS-KyberKey encapsulation (TLS, IKEv2, Signal)
FIPS 204ML-DSA (44 / 65 / 87)CRYSTALS-DilithiumGeneral-purpose digital signatures
FIPS 205SLH-DSA (SHA2 / SHAKE; 128/192/256)SPHINCS+Stateless hash-based signatures (firmware, code-signing)
FIPS 206 (in progress) [verify 2026-04-25]FN-DSAFALCONCompact lattice signatures
Selected for additional KEM standardizationHQCHQCCode-based KEM, ML-KEM backup

Hybrid Key Exchange (Transition Reality)

Why hybrid: classical (X25519) gives short-term confidentiality if the PQ algorithm is broken; PQ (ML-KEM-768) gives long-term confidentiality against “harvest-now-decrypt-later.” Both run in parallel and the shared secrets are concatenated.

  • TLS 1.3 codepoint: X25519MLKEM768 (group 0x11EC) — defined in draft-ietf-tls-ecdhe-mlkem (active IETF draft replacing the expired draft-kwiatkowski-tls-ecdhe-mlkem) [verify 2026-04-25].
  • Browser/CDN deployment: Chrome (since v131, late 2024) and Cloudflare enabled X25519MLKEM768 by default. Firefox shipped support behind config flag, then on by default [verify 2026-04-25 — confirm exact version].
  • Detection: modern testssl.sh --groups and OpenSSL 3.5+ (openssl s_client -groups X25519MLKEM768 -connect host:443) will negotiate hybrid groups when both endpoints support them [verify 2026-04-25].

Migration Posture for Auditors

  1. Inventory crypto-using assets (TLS endpoints, code-signing roots, VPN, document signing, secure boot, blockchain).
  2. Classify by data lifetime: anything that must remain confidential past ~2030 is a “harvest-now-decrypt-later” target — prioritize hybrid TLS + PQ key wrapping today.
  3. Track NIST SP 800-208 (stateful hash-based signatures: LMS, XMSS) for firmware/IoT code-signing where SLH-DSA is too large.
  4. CNSA 2.0 mandates ML-KEM-1024 / ML-DSA-87 / SLH-DSA-256 for U.S. NSS systems; full transition by 2033 [verify 2026-04-25].

Practical Tools

# liboqs - Open Quantum Safe (C library + bindings)
git clone https://github.com/open-quantum-safe/liboqs.git
# OpenSSL provider for liboqs (oqs-provider) enables PQ KEX/sigs in OpenSSL 3.x
git clone https://github.com/open-quantum-safe/oqs-provider.git
 
# pqcrypto (Python) - bindings to NIST round-3 / FIPS-203/204/205 reference impls
pip install pqcrypto
 
# Test endpoint negotiates hybrid PQ groups (requires OpenSSL 3.5+ with PQ enabled)
openssl s_client -groups X25519MLKEM768:X25519:secp256r1 \
                 -connect target.com:443 -tls1_3 </dev/null

Don’t roll your own PQ. Even more than classical crypto, PQ implementations are subtle (lattice arithmetic, constant-time sampling, side-channel resistance). Use liboqs / oqs-provider / pqcrypto / vendor libraries — never re-implement from the spec.


Tools Reference

Essential Tools

ToolPurposeInstallation
OpenSSLCrypto operations, certsapt install openssl (3.x; 3.5+ for PQ groups)
HashcatGPU password crackingapt install hashcat
John the Ripper (jumbo)CPU password crackingapt install john (distro) or build openwall/john jumbo branch for the widest format coverage
testssl.shSSL/TLS testinggit clone --depth 1 https://github.com/drwetter/testssl.sh (stable 3.2.x)
RsaCtfToolAutomated RSA attacks (Wiener, Boneh-Durfee, ROCA, Hastad, common modulus, FactorDB, Z3, …)git clone https://github.com/RsaCtfTool/RsaCtfTool.git
hashidHash identificationpipx install hashid
name-that-hash (nth)Modern hash identifier (more formats than hashid)pipx install name-that-hash
roca-detectDetect ROCA-vulnerable RSA keys (CVE-2017-15361)pip install roca-detect
hash_extenderLength-extension attack (replaces unmaintained HashPump)git clone https://github.com/iagox86/hash_extender && make
liboqs / oqs-providerPost-quantum primitives + OpenSSL 3 providergit clone https://github.com/open-quantum-safe/oqs-provider.git
SageMathCTF-grade number theory, lattice attacksapt install sagemath

Python Libraries

# Core crypto
pip install pycryptodome      # AES, RSA, ECC
pip install cryptography      # High-level API
 
# Math/Analysis
pip install gmpy2             # Fast math operations
pip install primefac          # Prime factorization
pip install ecdsa             # Elliptic curves
 
# Password hashing
pip install bcrypt            # bcrypt
pip install argon2-cffi       # Argon2
 
# Utilities
pip install base58            # Bitcoin addresses
pip install hashid            # Hash identification

Specialized Tools

ToolPurposeLink
PadBusterPadding oracle attack (Perl, original)https://github.com/AonCyberLabs/PadBuster
padrePadding oracle attack (Go, faster, modern)https://github.com/glebarez/padre
CyberChefMulti-tool for encoding/cryptohttps://gchq.github.io/CyberChef/
FactorDBInteger factorization databasehttp://factordb.com/
YAFUSelf-tuning integer factorizer (large composites)https://github.com/bbuhrow/yafu
msieve / cado-nfsNumber-field-sieve factorization for ≥512-bit nhttps://gitlab.inria.fr/cado-nfs/cado-nfs
SlitherSmart contract analyzerpip install slither-analyzer

Reference Resources

Comprehensive Knowledge Bases

  • CryptoHack - cryptohack.org
    • Interactive cryptography challenges and learning platform
    • Covers RSA, AES, elliptic curves, hash functions
    • Excellent for CTF preparation
  • Practical Cryptography for Developers - cryptobook.nakov.com
    • Modern cryptography handbook with Python examples
    • Covers symmetric/asymmetric crypto, digital signatures, key exchange
  • Crypto101 - crypto101.io
    • Introductory cryptography course (free book)
    • Explains fundamentals with practical examples
  • CyberChef Wiki - github.com/gchq/CyberChef/wiki
    • Documentation for CyberChef multi-tool
    • Encoding/decoding, crypto operations, data analysis

Attack Techniques & Exploits

RSA Specific Resources

Password Cracking Resources

SSL/TLS Testing Resources

Online Tools

  • CyberChef - gchq.github.io/CyberChef
    • Multi-tool for encoding, decoding, crypto operations
    • Visual recipe builder for data transformations
  • dcode.fr - dcode.fr
    • Classical cipher solver (Caesar, Vigenère, substitution)
    • Frequency analysis, cryptanalysis tools
  • Crackstation - crackstation.net
    • Online hash lookup (15 billion hashes)
    • Fast MD5/SHA1/NTLM cracking
  • Cipher Identifier - dcode.fr/cipher-identifier
    • Automatic cipher type detection

Cheat Sheets & Quick References

Vulnerability Databases

Post-Quantum Cryptography

Research & Academic Papers

  • IACR ePrint Archive - eprint.iacr.org
    • Cryptology research papers (pre-prints)
    • Latest attacks and cryptographic research
  • Applied Cryptography by Bruce Schneier - Classic cryptography textbook
    • Covers algorithms, protocols, implementation
  • The Joy of Cryptography - joyofcryptography.com
    • Free undergraduate-level cryptography textbook

CTF & Practice Platforms

Defensive Resources


Analysis:

Pentesting & Security:

OSINT & Process:

  • Legal & Ethics - Authorization, jurisdiction, export control (canonical)
  • OPSEC Plan - Handling of recovered keys, ciphertext, evidence custody

Cryptographic analysis spans defensive testing, CTF training, academic research, and offensive operations. Authorization and jurisdiction matter independently of intent — see Legal & Ethics for the canonical framework. Field-specific risks for this SOP:

  • Authorization: password cracking, padding-oracle attacks, RSA key recovery, and TLS scanning of third-party hosts can constitute unauthorized access (CFAA / Computer Misuse Act / equivalent statutes worldwide). Get written scope before running anything in this SOP against a system you do not own.
  • Wiretap / interception: decrypting captured traffic — even your own captures of someone else’s session — implicates wiretap statutes (e.g., U.S. ECPA, EU ePrivacy). Lab traffic only unless you have signed authorization or both-party consent.
  • Export control: cryptographic source code and certain dual-use tools (e.g., libraries implementing strong PQ KEMs) are subject to EAR (US) / Wassenaar / national export-control regimes. Be cautious sharing builds across borders; published open-source code is generally exempt but the exemption is narrow.
  • Recovered key material handling: treat recovered private keys, plaintext, and password lists as evidence — minimum, encrypt at rest with a fresh key; preferred, hand off to the engagement custodian per OPSEC Plan §evidence handling. Never paste recovered keys into public pastebins, third-party CTF “hint” sites, or LLM chat windows.
  • Disclosure: for vulnerabilities found incidentally (e.g., a misconfigured TLS deployment, a ROCA-vulnerable production key), follow coordinated disclosure — see Bug Bounty for the responsible-disclosure workflow.
  • CTF context: challenges shipped for cracking are in scope by definition; do not extend the same techniques to the platform’s own infrastructure or to other competitors’ systems.

Version: 2.1 Last Updated: 2026-04-25 Focus: Practical cryptanalysis for security research and CTF challenges Review Frequency: Semi-annual (medium-rot — tooling churn, CVE drift, post-quantum migration tracking)