← Back to Writeups
CUSTOMMediumCrypto

Двойной хэш (Double Hash)

XESXOR9/2/20263 min read
#crypto#custom#medium#double-encryption-with-identic#hex-encoding/decoding#rc4-stream-cipher-xor-cancella#web-service-interaction

Двойной хэш (Double Hash)

Platform: CUSTOM | Category: Crypto | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: Double encryption with identical keys, Hex encoding/decoding, RC4 stream cipher XOR cancellation attack, Web service interaction

Summary

Walkthrough of the CUSTOM Crypto Двойной хэш (Double Hash). Task: Flask web service with double RC4 encryption where user controls both keys. Solution: XOR cancellation attack - using identical keys (key1 == key2) causes the stream cipher to cancel itself, ret

Description

Один ключ хорошо, а два... хуже?!

A Flask web service with double RC4 encryption of the flag.

Analysis

Service Source Code

python
import random
from Crypto.Util.number import *

key = ?
FLAG = ?

@app.route('/double_hash/encrypt/<key1>/<key2>/')
def decrypt_flag(key1, key2):
    
    try:
        key_1 = bytes.fromhex(key1)
        key_2 = bytes.fromhex(key2)
    except:
        return {"error": "non-hexadecimal"}
    
    nonce = os.urandom(4).hex().encode()
    nonce1 = pbkdf2_hmac('sha256', key_1, b'salt', 100000, dklen=32) + nonce
    nonce2 = pbkdf2_hmac('sha256', key_2, b'salt', 100000, dklen=32) + nonce
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

    tempkey1 = SHA.new(key+nonce1).digest()
    tempkey2 = SHA.new(key+nonce2).digest()

    round1 = ARC4.new(tempkey1)
    firstEncryption = round1.encrypt(FLAG)

    round2 = ARC4.new(tempkey2)
    finalEncryption = round2.encrypt(firstEncryption)
    result = hexlify(finalEncryption + nonce).decode()

    return {"result": result}

Encryption Algorithm

  1. Accepts key1 and key2 in hex format
  2. Generates random nonce = os.urandom(4).hex().encode() (8 bytes)
  3. nonce1 = PBKDF2(key1, 'salt', 100000) + nonce
  4. nonce2 = PBKDF2(key2, 'salt', 100000) + nonce
  5. tempkey1 = SHA1(server_key + nonce1)
  6. tempkey2 = SHA1(server_key + nonce2)
  7. Double encryption: ARC4(tempkey2).encrypt(ARC4(tempkey1).encrypt(FLAG))
  8. Returns hex(ciphertext + nonce) ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Vulnerability: XOR Cancellation

RC4 (ARC4) is a stream cipher that works via XOR:

ciphertext = plaintext XOR keystream

If key1 == key2:

  • nonce1 == nonce2 (identical PBKDF2 output)
  • tempkey1 == tempkey2 (identical SHA1 hash)
  • Both RC4 instances generate identical keystream

Double encryption with the same key:

round1 = FLAG XOR keystream
round2 = round1 XOR keystream = FLAG XOR keystream XOR keystream = FLAG

XOR property: A XOR B XOR B = A

Result: the flag is returned in plaintext! ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Solution

Exploitation

bash
curl -s "http://62.173.140.174:11003/double_hash/encrypt/00/00/"

Response:

json
{"result": "434f444542597b443075626c335f683473685f336e637279707469306e7d3565393865653835"}

Decoding

python
result = '434f444542597b443075626c335f683473685f336e637279707469306e7d3565393865653835'

# Last 16 hex characters = nonce (os.urandom(4).hex().encode() = 8 bytes)
nonce_hex = result[-16:]  # '3565393865653835'
encrypted_hex = result[:-16]  # '434f444542597b443075626c335f683473685f336e637279707469306e7d'
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

# Decode the flag
flag = bytes.fromhex(encrypted_hex).decode()
print(flag)  # CODEBY{REDACTED}

Theory

Why Double RC4 Encryption is Dangerous

Unlike block ciphers (AES), where double encryption increases complexity, XOR-based stream ciphers have a self-inverse property:

E_k(E_k(m)) = m XOR keystream XOR keystream = m

Correct Implementation

For secure double encryption you need:

  1. Different keys (key1 != key2)
  2. Or different nonce for each round
  3. Or use a block cipher in CBC/GCM mode ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Alternative Solutions

Any Identical Keys

bash
curl "http://62.173.140.174:11003/double_hash/encrypt/deadbeef/deadbeef/"
curl "http://62.173.140.174:11003/double_hash/encrypt/41414141/41414141/"

All variants with key1 == key2 will return the flag in plaintext. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Key Takeaways / Lessons

  • Mastering Double encryption with identical keys, Hex encoding/decoding, RC4 stream cipher XOR cancellation attack, Web service interaction was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-01-02 • CUSTOM • Двойной хэш (Double Hash) • Difficulty: Medium