# Magic Image
For this challenge you were given two files encrypt.py and encrypted.png. Presumably encrypted.png was generated with encrypt.py script. Here are the contents of the encrypt.py.
```python#!/usr/bin/env python
def xor(s1, s2):    res = [chr(0)]*12    for i in range(len(res)):        q = ord(s1[i])        d = ord(s2[i])        k = q ^ d        res[i] = chr(k)    res = ''.join(res)    return res
def add_pad(msg):    l = 12 - len(msg)%12    msg += chr(l)*l    return msg
with open('flag.png') as f:    data = f.read()
data = add_pad(data)
with open('key') as f:    key = f.read()
enc_data = ''for i in range(0, len(data), 12):    enc = xor(data[i:i+12], key)    enc_data += enc
with open('encrypted.png', 'wb') as f:    f.write(enc_data)
```
Looking at the code we see that it simply has a twelve byte key that xors every byte of the file with, and we need to recover it to get the original png back.
The [PNG](http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html) file format has an 8 byte header of [137 80 78 71 13 10 26 10]. So we can obtain the first 8 bytes of the key by finding each byte, b, such that ```b ^ encrypted_header[i] = decrypted_header[i]```
What about the last 4 bytes however? Well looking at the add_pad function it's main job is to pad the decrypted file so that it is divisble by the key length. The way it does it is by padding it with the character value of the number of bytes that need to be added. This is easily reversible though. If it padded over four bytes than that means we will have the key and the encrpyted value. So all we need to do is figure out the pad length. This is done by finding the value such that ```key[i] ^ i == last[i]``` where last is the last 12 bytes of the encrypted file. It turns out that the pad length is seven in this case.
We just use that formula for last four bytes of the key replacing i with the padlength ```key[i] ^ pad_length == last[i]```. Now we will have the full key and can reverse the whole image by running the encryption algorithm on itself.
Here is the full code used to solve it.
```python#!/usr/bin/env python
def xor(s1, s2):    res = [chr(0)]*12    for i in range(len(res)):        q = ord(s1[i])        d = ord(s2[i])        k = q ^ d        res[i] = chr(k)    res = ''.join(res)    return res
# PNG header valuesords = [137, 80, 78, 71, 13, 10, 26, 10]
# Read the whole encrypted file# and get the first 8 and last 12 bytes for later usewith open('encrypted.png') as f:    r = f.read()    enc_ords = r[:8]    enc_ords = [ord(x) for x in enc_ords]    last = r[len(r) - 12:]    last = [ord(x) for x in last]
# Get the first eight bytes of the keykey = []for i in range(0,len(ords)):    for x in range(255):        if ords[i] ^ x == enc_ords[i]:            key.append(x)            break
# Get the pad length and valuefor x in range(1,8):    if key[x] ^ x == last[x]:        pad = x
# Get the last four bytes of the keyfor i in range(8,12):    for x in range(255):        if x ^ pad == last[i]:            key.append(x)
# Put the key into a stringkey = ''.join([chr(x) for x in key])
# decrypt the fileenc_data = ''for i in range(0, len(r), 12):    enc = xor(r[i:i+12], key)    enc_data += enc
# write the decrypted image outwith open('decrypt.png', 'wb') as f:    f.write(enc_data)
```
And here is the decrypted image file with the flag
![Flag Image](https://i.imgur.com/JdSTCUz.png) 