PicoCTF: Tap into Hash
A step-by-step solution for the PicoCTF Tap into Hash challenge.
Today, we’re diving into the picoCTF challenge: Tap into Hash 2025. Let’s break it down step by step and decrypt the given ciphertext.
📊 Challenge Overview
The provided Python script accepts an argument and runs a main function that displays the encrypted string. Before writing a decryption function, let’s first analyze how the encryption process works.
🔑 Solution
Breaking Down the Encryption Function
The encrypt function takes three parameters:
plaintext: The original messageinner_txt: A string inserted in betweenkey: The encryption key
Encryption Process
Splitting the Plaintext: the function finds the midpoint of plaintext, splits it into first and second, then inserts
inner_txtin between.Padding the Text: the modified plaintext is processed in 16-byte blocks. If it’s shorter, padding is added.
Hashing the Key: the key is hashed using SHA-256 to ensure a fixed length.
XOR Encryption: the function iterates over the plaintext in 16-byte blocks and XORs each block with
key_hash.The result is stored in ciphertext.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def encrypt(plaintext, inner_txt, key):
midpoint = len(plaintext) // 2
first_part = plaintext[:midpoint]
second_part = plaintext[midpoint:]
modified_plaintext = first_part + inner_txt + second_part
block_size = 16
plaintext = pad(modified_plaintext, block_size)
key_hash = hashlib.sha256(key).digest()
ciphertext = b''
for i in range(0, len(plaintext), block_size):
block = plaintext[i:i + block_size]
cipher_block = xor_bytes(block, key_hash)
ciphertext += cipher_block
return ciphertext
Decrypt function
Since the encryption method is XOR-based, decryption is straightforward:
- XOR the encrypted string with the same key → This will recover the plaintext.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import ast
import re
def decrypt(plaintext, key):
block_size = 16
key_hash = hashlib.sha256(key).digest()
ciphertext = b''
for i in range(0, len(plaintext), block_size):
block = plaintext[i:i + block_size]
cipher_block = xor_bytes(block, key_hash)
ciphertext += cipher_block
return ciphertext
def main(token):
with open(token, "r") as file:
data = {}
for line in file:
if ":" in line:
key, value = line.split(":", 1)
key = key.strip()
value = value.strip()
try:
data[key] = ast.literal_eval(value)
except (SyntaxError, ValueError):
data[key] = value
plain_text = decrypt(data['Encrypted Blockchain'], data['Key'])
pattern = r"picoCTF\{.*?\}"
match = re.search(pattern, str(plain_text))
if match:
print(match.group())
else:
print("No picoCTF flag found.")
1
python block_chain.py enc_flag
🚩 Flag Capture
1
picoCTF{block_3SRhViRbT1qcX_XUjM0r49cH_qCzmJZzBK_8bb7bc38}
