Crypto-100 ECXOR

After looking into encrypt and decrypt function in ecxor_handout_100.py, it seems it’s using elliptic curve cryptography, but we’ll just focus on input and output. Encryption is taking place byte by byte, each byte is converted into a point.

Also the rfc module isn’t provided, so I looked up on internet and found rfc8032 and grabbed the module code from there, you can find it in rfc8032.py

In main function,

flag = 'flag{secret_placeholder_flag_decrypt_for_real_flag}' + open('english_padding.txt', 'r').read(200)

we can clearly see that 200 chars of english text is appended to the flag. Now let’s find out the length of the flag.

Start off by reading the ciphertext and parsing the points from it

ctext = open("ciphertext", "r").readlines()[0].split(';')
points = [point_decompress(base64.b64decode(p)) for p in ctext]

len(points) gives us 258, so this means, 258-200 = 58, that is the length of flag. We also know the flag structure, flag{…}

We can also see that the encryption algo encrypts byte by byte, so we can try to encrypt ‘f’ and try to match the output with ciphertext’s first byte and find the key’s first byte. Key length is given as 12

flag = "flag{"
i = 0
key = 0
while(key < 256):
    decrypted = frompoint(point_add(negate(topoint(key)), points[i]))
    if(dec == ord(flag[i])):
        print(chr(dec), key, chr(key))
        i += 1
        key = 0
    key += 1

So after running it for 5 iterations, we get these key bytes: 223 8 70 241 26 Since 58th char of plaintext is } (flag structure), we know one more byte of key, i.e. 12*4+10, 10th byte Running this function for this value gives us 13

Let’s try to decrypt the given ciphertext using only these 6 identified bytes, may be we can get some insight.

So, I slightly modified the decryption function to decrypt using given key as an array.

def decrypt(key, points):
    ptext = ''
    for (x, y) in zip(cycle(key), points):
        try:
            pt = chr(frompoint(point_add(negate(topoint(x)), y)))
            ptext += pt
        except:
            ptext += '*'
    return ptext

It also replaces unprintable characters by *s

Now we define our key as: key = [223, 8, 70, 241, 26, 0, 0, 0, 0, 13, 0, 0] and try to decrypt the ciphertext

pt = decrypt(key, points)
print(pt)

We get

flag{±***rĄizing©***nȊe_to_«***tÕyry_gr¹***_̋_not_±***}…af youq***gҁng tojto aj***,ƒ…y dea¼***sād Ali­***"¬?ll haÀ*ñ*o׀ing m¹***tÒ8do wi¾***oØF Mindj* Alic¯***sƒ‚ust b¯***n̆g to ¾***kƒŒo her½***,ƒ:Now, Á*** ą I toj***w̌h thi½***eČure,

Cool, made some progress :)

Now we can guess/comlete missing/corrupted english words and try to find the remaining key bytes.

After trying for a while, i looked at ±***rĄizing, I thought this was a single word, so I looked up on the internet for words ending with izing and of 12 chars, tried some of them manually, also thought of writing a script but I was lazy :P

I also looked at the encryption algorithm for any loopholes, but couldn’t find any and started working on another problem.

Came again on this one and again tried a few words, and guess what, it worked this time :) The word was ‘generalizing’, let’s try running the same script again, This time our initial flag is: flag{generalizing, so we got 17 bytes, more than enough to find the whole key, and running the key finding script again, resulted in all 12 key bytes: key = [223, 8, 70, 241, 26, 74, 225, 231, 228, 13, 99, 24]

Let’s now try to decrypt, woah, we got the flag:

flag{generalizing_vignere_to_arbitrary_groups_is_not_good}"If you're going toturn into a pig, my dear," said Alice, "I'll have
nothing more to do with you. Mind now!"

Alice was just beginning to think to herself, "Now, what am I to do with
this creature, w

I don’t know if we were supposed to solve it by guessing, but I am looking for another ways of solving this challenge.