Description
The provided blockchain script hashes the key with SHA-256 and XORs every 16-byte block with that digest. With the key and ciphertext in hand, decrypting is as simple as repeating the XOR.
Download both `block_chain.py` and `enc_flag` from the challenge files.
Read the script to see how `xor_bytes` and the block loop work; the same routine can be run in reverse.
wget https://challenge-files.picoctf.net/c_verbal_sleep/ba64ef56074be4d9f1b047eb451185d84de7c490e264b9ea6e645bd9b0956c01/block_chain.py
wget https://challenge-files.picoctf.net/c_verbal_sleep/ba64ef56074be4d9f1b047eb451185d84de7c490e264b9ea6e645bd9b0956c01/enc_flag
Solution
- Step 1Reimplement xor_bytesCopy the helper function from the source: it simply XORs each ciphertext byte with the corresponding `key_hash` byte. You’ll use the same function to decrypt.
- Step 2Derive the keystreamHash the provided key with SHA-256 (`key_hash = hashlib.sha256(key).digest()`) so you have the exact keystream the challenge used.
- Step 3Loop through the blocksIterate over the ciphertext in 16-byte chunks, XOR each block with `key_hash`, and append the result. Printing the combined buffer reveals the flag embedded among hex strings; grep it for convenience.python3 - <<'PY' import hashlib from pathlib import Path def xor_bytes(a, b): return bytes(x ^ y for x, y in zip(a, b)) encrypted = Path('enc_flag').read_bytes() key = b"\x8b\x9a\x00G\xfe\xb3\xf3\x93\xdb\xa8yT\xfe\x15\x87a\xf4\xdf\x00\x8d\xee\xab\xd9\t^|\x04(%\x81\x9e\xf8" block_size = 16 key_hash = hashlib.sha256(key).digest() flag = b'' for i in range(0, len(encrypted), block_size): block = encrypted[i:i+block_size] flag += xor_bytes(block, key_hash) print(flag.decode(errors='ignore')) PYpython3 solve.py | grep -o 'picoCTF{.*}' --color=none
Flag
picoCTF{block_3SRhViRbT1qcX_XUjM0r49cH_qCzmJZzBK_6064...}
Padding bytes leave stray characters, so piping the output through `grep -o 'picoCTF{.*}'` is the quickest way to isolate the flag.