from Crypto.Cipher import DES
import binascii

IV = '13371337'

WEAK_KEYS = [
   '0101010101010101',
   'FEFEFEFEFEFEFEFE',
   'E0E0E0E0F1F1F1F1',
   '1F1F1F1F0E0E0E0E',
   '011F011F010E010E',
   '1F011F010E010E01',
   '01E001E001F101F1',
   'E001E001F101F101',
   '01FE01FE01FE01FE',
   'FE01FE01FE01FE01',
   '1FE01FE00EF10EF1',
   'E01FE01FF10EF10E',
   '1FFE1FFE0EFE0EFE',
   'FE1FFE1FFE0EFE0E',
   '01011F1F01010E0E',
   '1F1F01010E0E0101',
   'E0E01F1FF1F10E0E',
   '0101E0E00101F1F1',
   '1F1FE0E00E0EF1F1',
   'E0E0FEFEF1F1FEFE',
   '0101FEFE0101FEFE',
   '1F1FFEFE0E0EFEFE',
   'E0FE011FF1FE010E',
   '011F1F01010E0E01',
   '1FE001FE0EF101FE',
   'E0FE1F01F1FE0E01',
   '011FE0FE010EF1FE',
   '1FE0E01F0EF1F10E',
   'E0FEFEE0F1FEFEF1',
   '011FFEE0010EFEF1',
   '1FE0FE010EF1FE01',
   'FE0101FEFE0101FE',
   '01E01FFE01F10EFE',
   '1FFE01E00EFE01F1',
   'FE011FE0FE010EF1',
   'FE01E01FFE01F10E',
   '1FFEE0010EFEF101',
   'FE1F01E0FE0E01F1',
   '01E0E00101F1F101',
   '1FFEFE1F0EFEFE0E',
   'FE1FE001FE0EF101',
   '01E0FE1F01F1FE0E',
   'E00101E0F10101F1',
   'FE1F1FFEFE0E0EFE',
   '01FE1FE001FE0EF1',
   'E0011FFEF1010EFE',
   'FEE0011FFEF1010E',
   '01FEE01F01FEF10E',
   'E001FE1FF101FE0E',
   'FEE01F01FEF10E01',
   '01FEFE0101FEFE01',
   'E01F01FEF10E01FE',
   'FEE0E0FEFEF1F1FE',
   '1F01011F0E01010E',
   'E01F1FE0F10E0EF1',
   'FEFE0101FEFE0101',
   '1F01E0FE0E01F1FE',
   'E01FFE01F10EFE01',
   'FEFE1F1FFEFE0E0E',
   '1F01FEE00E01FEF1',
   'E0E00101F1F10101',
   'FEFEE0E0FEFEF1F1'
]
def getNibbleLength(offset):
   if str(offset)[0]=="9":
       return len(str(offset))+1
   return len(str(offset))

def duck(aChr):
   try:
       return int(aChr)
   except:
       return "abcdef".index(aChr)+11

def encodeText(plainText,offset):
   hexEncoded = plainText.encode("hex")
   nibbleLen = getNibbleLength(offset)
   output = ""
   for i in range(0,len(hexEncoded),2):
       hexByte = hexEncoded[i:i+2]
       try:
           output += str(duck(hexByte[0]) + offset).rjust(nibbleLen,"0")
           output += str(duck(hexByte[1]) + offset).rjust(nibbleLen,"0")
       except:
           continue
   return output

def decodeText(encoded,offset):
   nibbleLen = getNibbleLength(offset)
   output = ""
   for i in range(0, len(encoded), nibbleLen):
       chunk = encoded[i:i+nibbleLen]
       output += hex(int(chunk) - offset)[-1]
   return output.decode("hex")

def padInput(input):
   bS = len(input)/8
   if len(input)%8 != 0:
       return input.ljust((bS+1)*8,"_")
   return input

def desEncrypt(input,key):
   cipher = DES.new(key, DES.MODE_OFB, IV)
   msg = cipher.encrypt(padInput(input))
   return msg

def unpadInput(input):
   return input.rstrip('_')

def desDecrypt(input,key):
   cipher = DES.new(key, DES.MODE_OFB, IV)
   msg = cipher.decrypt(input)
   return unpadInput(msg)

def createKey(hex,fileName):
   with open(fileName, 'wb') as f:
       f.write(binascii.unhexlify(hex))

def createChallenge():
   createKey("INSERT_SOME_KEY","key1")
   createKey("SOME_OTHER_KEY","key2")

   plainText = open('FLAG.txt').read()
   key1 = open('key1').read()

   byte = desEncrypt(plainText,key1)
   key2 = open('key2').read()

   cipherText = desEncrypt(byte,key2)
   cipherText = encodeText(binascii.hexlify(cipherText),9133337)
   with open('FLAG.enc', 'w') as f:
       f.write(cipherText)

def findKeys(plaintext, ciphertext):
   for key1 in WEAK_KEYS:
       for key2 in WEAK_KEYS:
           if desDecrypt(desDecrypt(ciphertext, binascii.unhexlify(key1)), binascii.unhexlify(key2)) == plaintext:
               return [key1, key2]

key1, key2 = findKeys(open('DES2Bytes.txt').read(), binascii.unhexlify(decodeText(open('DES2Bytes.enc').read(),9133337)))
print desDecrypt(desDecrypt(binascii.unhexlify(decodeText(open('FLAG.enc').read(),9133337)), binascii.unhexlify(key1)), binascii.unhexlify(key2))