Enigma
Enigma
Platform: hackerlab | Category: Crypto | Type: Challenge | Difficulty: Medium | OS: NA | Author: XESXOR | Date: 2025-12-25 | Status: Solved Techniques: Known Plaintext Attack (KPA), Many-Time Pad Attack, XOR Key Recovery
Summary
Task: 100 XOR-encrypted messages with 64-bit key, known plaintext prefix "Hello Alice". Solution: Many-Time Pad attack - recovered key using known plaintext XOR, decrypted all messages to find real flag among 99 fakes.
Enigma — hackerlab
Description
Мы перехватили 100 шифровок, отправленных 28 июля 2025. Известно, что длина ключа 64 бит. Также известно, что открытый текст каждой шифровки начинается со слов "Hello Alice"
Analysis
Initial Data
- 100 encrypted messages (hex-encoded)
- Key length: 64 bits = 8 bytes
- Known plaintext: each message starts with "Hello Alice"
Identified Vulnerability
Many-Time Pad (Key Reuse Attack)
Analysis of 100 ciphertexts revealed:
- All ciphertexts have identical first 8 bytes — this means the same key is used for all messages
- Known plaintext of first 8 characters:
Hello Al(exactly 8 bytes = key length)
Attack Mathematics
XOR encryption:
Ciphertext = Plaintext ⊕ Key
With known plaintext:
Key = Ciphertext ⊕ Plaintext
Knowing the first 8 bytes of plaintext (Hello Al) and the first 8 bytes of any ciphertext, we can recover the full 8-byte key.
Solution
Step 1: Key Recovery
python read-only • copy allowedimport binascii known_plaintext = b"Hello Al" # 8 bytes = key length # First ciphertext (first 8 bytes) ciphertext_prefix = binascii.unhexlify("45c07661e012e844") # XOR to get the key key = bytes(c ^ p for c, p in zip(ciphertext_prefix, known_plaintext)) print(f"Key: {key.hex()}") # 0D A0 16 05 88 77 89 25
Step 2: Decrypting All Messages
python read-only • copy allowed#!/usr/bin/env python3 import binascii def xor_bytes(b1, b2): return bytes(a ^ b for a, b in zip(b1, b2)) def decrypt(ciphertext_hex, key): ciphertext = binascii.unhexlify(ciphertext_hex) plaintext = bytearray() for i in range(len(ciphertext)): plaintext.append(ciphertext[i] ^ key[i % len(key)]) return plaintext # Recovered key key = bytes([0x0D, 0xA0, 0x16, 0x05, 0x88, 0x77, 0x89, 0x25]) with open('ciphertexts.txt', 'r') as f: ciphertexts = [line.strip() for line in f if line.strip()] for i, ct in enumerate(ciphertexts): pt = decrypt(ct, key) try: text = pt.decode('utf-8') if 'CODEBY' in text: print(f"[!] Message {i}: {text}") else: print(f"{i}: {text}") except: print(f"{i}: {pt}")
Result
- 99 messages contained fake flags:
Hello Alice, FAKE-FLAG-XXXX... - Message #11 contained the real flag
Defense
- Never use the same key twice in stream cipher / XOR
- Use a unique nonce/IV for each message
- Apply authenticated encryption (AES-GCM, ChaCha20-Poly1305)
- For OTP — the key must be longer than the message and used only once
References
- Many-Time Pad Attack
- Known-Plaintext Attack