#!/usr/bin/env sage
fromsage.allimport*importstring,base64,mathfromflagimportflagALPHABET=string.printable[:62]+'\\='F=list(GF(64))defkeygen(l):key=[F[randint(1,63)]for_inrange(l)]key=math.prod(key)# Optimization the key length :D
returnkeydefmaptofarm(c):assertcinALPHABETreturnF[ALPHABET.index(c)]defencrypt(msg,key):m64=base64.b64encode(msg)enc,pkey='',key**5+key**3+key**2+1forminm64:enc+=ALPHABET[F.index(pkey*maptofarm(chr(m)))]returnenc# KEEP IT SECRET
key=keygen(14)# I think 64**14 > 2**64 is not brute-forcible :P
enc=encrypt(flag,key)print(f'enc = {enc}')
I've never used sage before, but I've managed to find the documentation.
keygen(l) generates a random key and returns it. maptofarm(c) verifies if the given char is in alphabet, and if it is it returns the element from list F that is at the same index as is c in the alphabet. encrypt(msg, key) first encodes the message using base64. After it uses the provided key to generate another key that is used to encrypt the base 64 encoded message. In the end it returns the encrypted message.
To solve this problem I've used the following script:
#!/usr/bin/env sage
fromsage.allimport*importstring,base64,mathflag=b'ASIS'ALPHABET=string.printable[:62]+'\\='F=list(GF(64))defprod(list):prod=1foriteminlist:prod*=itemreturnproddefkeygen(l):key=[F[randint(1,63)]for_inrange(l)]key=prod(key)# Optimization the key length :D
returnkeydefmaptofarm(c):assertcinALPHABETreturnF[ALPHABET.index(c)]defencrypt(msg,key):m64=b'Q'enc,pkey='',key**5+key**3+key**2+1forminm64:enc+=ALPHABET[F.index(pkey*maptofarm(chr(m)))]pkey=F[8]/maptofarm(chr(m))print(pkey)returnpkey# KEEP IT SECRET
key=keygen(14)# I think 64**14 > 2**64 is not brute-forcible :P
pkey=encrypt(flag,key)defsolve(enc,pkey):m64=''forcharinenc:ind=ALPHABET.index(char)m2f=F[ind]/pkeym64+=ALPHABET[F.index(m2f)]print('64: ',m64)enc='805c9GMYuD5RefTmabUNfS9N9YrkwbAbdZE0df91uCEytcoy9FDSbZ8Ay8jj'solve(enc,pkey)
Long story short: it does the reverse operations. I've modified the encrypt to return the pkey by doing the reverse operations. The solve(enc, pkey) takes as arguments the encrypted message and the pkey found previously. It takes every char from the encrypted message and does the reverse operations of the encrypt message. After I've used this site to decode the flag.