CR2 Many time secrets

Crypto - 100 Points

This time Fady learned from his old mistake and decided to use onetime pad as his encryption technique, but he never knew why people call it one time pad!

File: msg

Writeup

OneTime Pad is the strongest cipher ever. It has been proved that it can’t be cracked even if the attacker have unlimited memory, computing power and time.
But this is true if and only if the key is single-use, truly random and have the same lenght as the message.

In the challenge we have 11 messages encrypted with the same key.

Note: Someone resolved this callenge with featherduster, an automatic tool that do analisys on the cyphertext and give you the message directly (in this case).
We think that this type of automatic tool is ‘useless’ in this type of competition, where participant should resolve challenges by thinking with their own heads.
We resolved the challenge manually, anyway the tool was explicitly allowed by the AlexCTF organizer.

Since we know that the flag format is ALEXCTF{flag} we started XORing every message with the first part of the key. (see Step 1 in the final script)

And From the first message we get: 'Dear Fri'

So we guess that the first message was starting with 'Dear Friend, ', XORing this with the first cypertext returned the first part of the key ALEXCTF{HERE_.
At this point we already got the flag just by guessing but we wanted to verify that step by step. A simple XOR would have worked

We XORed again every message with the new key above (see Step 3 in the final script).

The last deciphered message was 'ncryption sch'. Obviously (e)'ncryption scheme ', so we XORed that to get another part of the key ALEXCTF{HERE_GOES.

Again, by XORing the new key with every cyphertext the third message resulted in: 'sed One time pad e'
That is obviously 'sed One time pad encryptio'(n) (note the message length).

Annnnnd…… ALEXCTF{HERE_GOES_THE_KEY}

Final script for the record

#!/usr/bin/env python3

import binascii

def dec(msg, key):
    '''
    Simple char-by-char XOR with a key (Vigenere, Vernam, OTP)
    '''
    m = ""
    for i in range(0, len(key)):
        m += chr(msg[i] ^ ord(key[i]))
    return m

######################################

lines = []

with open("msg","r") as f:
    # Read lines from file and decode Hex
    ls = f.readlines()
    for l in ls:
        lines.append(binascii.unhexlify(l[:-1]))

# Step 1: Decode each line with the known key
k = "ALEXCTF{"
mes = []
for l in lines:
    m = dec(l,k)
    mes.append(m)
print(mes)

# Step 2: Guess some part of the first message 'Dear Fri'
k = "Dear Friend, "
m = dec(lines[0],k)
print(m)

# Step 3: Decode each line with the new known key
k = "ALEXCTF{HERE_"
mes = []
for l in lines:
    m = dec(l,k)
    mes.append(m)
print(mes)

# Step 4: Guess some part of the last message 'ncryption sc'
k = 'ncryption scheme '
m = dec(lines[-1],k)
print(m)

# Step 5: Decode each line with the new known key
k = "ALEXCTF{HERE_GOES_"
mes = []
for l in lines:
    m = dec(l,k)
    mes.append(m)
print(mes)

# Step 6: Guess all the second message 'sed One time pad e'
# the third message is 'n scheme, I heard '
# so we can retrive the complete key
k = 'sed One time pad encryptio'  
m = dec(lines[2],k)
print(m)

    
'''
['Dear Fri', 'nderstoo', 'sed One ', 'n scheme', 'is the o', 'hod that', ' proven ', 'ever if ', 'cure, Le', 'gree wit', 'ncryptio']
ALEXCTF{HERE_
['Dear Friend, ', 'nderstood my ', 'sed One time ', 'n scheme, I h', 'is the only e', 'hod that is m', ' proven to be', 'ever if the k', 'cure, Let Me ', 'gree with me ', 'ncryption sch']
ALEXCTF{HERE_GOES
['Dear Friend, This ', 'nderstood my mista', 'sed One time pad e', 'n scheme, I heard ', 'is the only encryp', 'hod that is mathem', ' proven to be not ', 'ever if the key is', 'cure, Let Me know ', 'gree with me to us', 'ncryption scheme a']
ALEXCTF{HERE_GOES_THE_KEY}
'''