| Looks like | Likely cipher |
|---|---|
| Only A-Z, spaces | Classical (Caesar, Vigenère, sub) |
| Base64 string | Encoded, not encrypted — decode first |
| Hex string | XOR, AES-ECB raw, or just encoding |
| Large decimal n,e,c | RSA |
| Two large hex numbers | ECC (r,s) ECDSA signature |
| Repeating blocks (hex) | AES-ECB — block pattern visible |
| Dots/dashes | Morse code |
| Binary groups | Binary → ASCII |
| Numbers 0-25 | Caesar / affine substitution |
| Mixed symbols | Substitution / pigpen / Polybius |
# Always try these first echo "<string>" | base64 -d echo "<hex>" | xxd -r -p echo "<string>" | tr 'A-Za-z' 'N-ZA-Mn-za-m' # ROT13 # CyberChef "Magic" — auto-detect # https://gchq.github.io/CyberChef/#recipe=Magic # dcode.fr — cipher identifier # https://www.dcode.fr/cipher-identifier # Python quick decode python3 -c " import base64, binascii s = 'your_string' print(base64.b64decode(s)) # base64 print(bytes.fromhex(s)) # hex print(base64.b32decode(s)) # base32 "
# Brute force all 26 shifts python3 -c " ct = 'KHOOR ZRUOG' for shift in range(26): print(shift, ''.join(chr((ord(c)-65-shift)%26+65) if c.isupper() else chr((ord(c)-97-shift)%26+97) if c.islower() else c for c in ct)) " # ROT13 (shift=13) echo "cvpbPGS{..." | tr 'A-Za-z' 'N-ZA-Mn-za-m' # ROT47 (printable ASCII) echo "E:4@r%u..." | tr '!-~' 'P-~!-O'
# Find key length with Index of Coincidence # or Kasiski test — use online tools # Python solve with known key python3 -c " ct = 'LXFOPVEFRNHR' key = 'LEMON' pt = '' for i,c in enumerate(ct): if c.isalpha(): shift = ord(key[i%len(key)].upper()) - 65 pt += chr((ord(c.upper())-65-shift)%26+65) else: pt += c print(pt) " # Automated: use quipqiup.com or dcode.fr
# Monoalphabetic substitution python3 -c " from collections import Counter ct = 'your ciphertext here' freq = Counter(c.upper() for c in ct if c.isalpha()) for ch, n in freq.most_common(): print(ch, n) # English: E T A O I N S H R D L C U M W F G Y P B V K J X Q Z " # quipqiup.com — automated sub cipher solver # cryptogram-solver.com # Known plaintext: if you know part of plaintext # map known chars → build substitution alphabet
| Cipher | Solve |
|---|---|
| Atbash | A↔Z, B↔Y: tr 'A-Za-z' 'ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba' |
| Rail fence | dcode.fr/rail-fence-cipher |
| Playfair | dcode.fr/playfair-cipher |
| Polybius | Map pairs to 5×5 grid |
| Bacon | A/B groups → 5 bits → letter |
| Columnar trans. | Reorder columns, read rows |
| Morse | dcode.fr or CyberChef |
| Affine | E(x)=ax+b mod 26, brute a∈{1,3,5,7…} |
# Single-byte XOR brute force python3 -c " ct = bytes.fromhex('1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736') for key in range(256): pt = bytes(b ^ key for b in ct) if all(32 <= c < 127 for c in pt): print(hex(key), pt) " # Repeating-key XOR (Vigenère-like) python3 -c " ct = bytes.fromhex('...') key = b'ICE' pt = bytes(ct[i] ^ key[i%len(key)] for i in range(len(ct))) print(pt) " # XOR two ciphertexts (same key → key cancels) # ct1 XOR ct2 = pt1 XOR pt2 python3 -c " c1 = bytes.fromhex('...') c2 = bytes.fromhex('...') print(bytes(a^b for a,b in zip(c1,c2))) "
# Hamming distance method python3 -c " def hamming(a, b): return sum(bin(x^y).count('1') for x,y in zip(a,b)) ct = bytes.fromhex('...') for ks in range(2, 41): score = hamming(ct[:ks], ct[ks:2*ks]) / ks print(ks, score) # Lowest score = most likely key length " # Once key length known → single-byte XOR each column python3 -c " ct = bytes.fromhex('...') ks = 3 # key size key = [] for i in range(ks): col = ct[i::ks] best = max(range(256), key=lambda k: sum(chr(b^k) in 'etaoinshrdlu ' for b in col)) key.append(best) print(bytes(key)) "
# RSA: c = m^e mod n, m = c^d mod n # d = modular inverse of e mod phi(n) # e=3, small m: cube root (no mod needed) python3 -c " import gmpy2 c = 0xdeadbeef... m, exact = gmpy2.iroot(c, 3) if exact: print(bytes.fromhex(hex(m)[2:])) " # e=65537 with small n: factor with factordb # http://factordb.com/ — paste n # Factor small n directly python3 -c " from sympy import factorint n = 0x... print(factorint(n)) " # Once p,q known → decrypt python3 -c " from Crypto.Util.number import inverse, long_to_bytes p,q,e,c = ...,...,...,... phi = (p-1)*(q-1) d = inverse(e, phi) m = pow(c, d, p*q) print(long_to_bytes(m)) "
| Attack | Condition | Tool |
|---|---|---|
| Fermat factoring | p,q close together | Custom script |
| Wiener's attack | d small (d < n^0.25) | owiener lib |
| Common factor | Two n share a prime | gcd(n1,n2) |
| Broadcast attack | Same m, e=3, 3 different n | CRT + cube root |
| Padding oracle | PKCS#1 v1.5 | Custom |
| Low public exp | e=3, small m | Cube root |
| Boneh-Durfee | d < n^0.292 | SageMath script |
| factordb | n already factored online | factordb.com |
# Swiss army knife for RSA CTF challenges RsaCtfTool.py --publickey pub.pem --uncipherfile cipher.bin RsaCtfTool.py -n <n> -e <e> --uncipher <c> # Try all attacks at once RsaCtfTool.py -n <n> -e <e> --uncipher <c> --attack all # Multiple public keys (common modulus) RsaCtfTool.py --publickey "*.pem" --attack all # Fermat factoring manually python3 -c " import gmpy2 n = 0x... a = gmpy2.isqrt(n) + 1 while True: b2 = a*a - n b, exact = gmpy2.isqrt_rem(b2) if exact == 0: break a += 1 p,q = int(a-b), int(a+b) print(p, q) "
| Mode | Identify | Attack |
|---|---|---|
| ECB | Identical 16-byte blocks in CT | Cut-and-paste, chosen plaintext weak |
| CBC | IV prepended, no block repeat | Padding oracle, bit-flip |
| CTR | Keystream XOR, no padding | Reused nonce → XOR CTs |
| OFB | Like CTR, stream cipher | Reused IV → XOR |
| CFB | Feedback mode | Bit-flipping |
| GCM | Authenticated, 12-byte nonce | Nonce reuse → auth forgery |
# ECB detection: submit 32 identical bytes # If bytes 0-15 == bytes 16-31 → ECB mode python3 -c " ct = encrypt(b'A' * 32) print('ECB!' if ct[0:16] == ct[16:32] else 'Not ECB') " # Byte-at-a-time ECB decryption # Encrypt: [A*15 + unknown_byte] → compare with # all [A*15 + guess] until match # CBC bit-flip: flip bit in CT block i # → predictably flips bit in PT block i+1 python3 -c " ct = bytearray(ciphertext) # target offset in block i+1 = offset + 16 ct[offset] ^= ord('a') ^ ord('A') # change 'a' → 'A' in next block "
# If nonce reused: ct1 XOR ct2 = pt1 XOR pt2 # Known plaintext → recover keystream → decrypt all python3 -c " # If you know pt1 (or part of it): ks = bytes(a^b for a,b in zip(ct1, pt1)) # keystream pt2 = bytes(a^b for a,b in zip(ct2, ks)) print(pt2) " # Padding oracle (CBC) — pwntools has one # Or use: padbuster, POET padbuster http://target/decrypt "<ciphertext>" 16
# Identify hash type hashid <hash> hash-identifier <hash> # 32 hex = MD5, 40 = SHA1, 64 = SHA256, 128 = SHA512 # Crack with hashcat hashcat -m 0 hash.txt rockyou.txt # MD5 hashcat -m 100 hash.txt rockyou.txt # SHA1 hashcat -m 1400 hash.txt rockyou.txt # SHA256 hashcat -m 1800 hash.txt rockyou.txt # SHA512crypt # Online rainbow tables # crackstation.net / hashes.com / md5decrypt.net # Length extension attack (MD5, SHA1, SHA256) hash_extender --data original --secret-length 16 \ --append ";admin=true" --signature <hash>
# Vulnerable: HMAC(key || msg) using MD5/SHA1/SHA256 # You know: hash(key||msg), len(key), msg # You can forge: hash(key||msg||padding||append) # hlextend Python library python3 -c " import hlextend sha = hlextend.new('sha256') new_msg, new_hash = sha.extend( b';admin=true', # data to append b'original_message', # original data 16, # secret key length 'original_hash_hex' # known hash ) print(new_msg.hex(), new_hash) "
# ECDSA signature: (r, s) with nonce k # Nonce reuse: same k → same r # k = (z1-z2) * modInverse(s1-s2, n) # d = (s*k - z) * modInverse(r, n) python3 -c " from Crypto.Util.number import inverse # if r1 == r2 (same nonce k used): k = (z1 - z2) * inverse(s1 - s2, n) % n d = (s1 * k - z1) * inverse(r1, n) % n print(hex(d)) # private key " # Invalid curve attack, small subgroup # Use SageMath for discrete log on weak curves
| Scenario | Tool/Approach |
|---|---|
| Unknown cipher | CyberChef Magic, dcode.fr |
| RSA all-in-one | RsaCtfTool.py |
| Prime factoring | factordb.com, yafu, msieve |
| Discrete log | SageMath discrete_log() |
| AES padding oracle | padbuster, pwntools |
| Hash cracking | hashcat, john, crackstation |
| XOR key finding | xortool, CyberChef |
| PRNG prediction | z3, randcrack (Mersenne) |
| LCG prediction | Known outputs → solve for params |