Crypto CTF 2021 | Farm

#cryptoctf2021

#!/usr/bin/env sage

from sage.all import *
import string, base64, math
from flag import flag

ALPHABET = string.printable[:62] + '\\='

F = list(GF(64))

def keygen(l):
    key = [F[randint(1, 63)] for _ in range(l)] 
    key = math.prod(key) # Optimization the key length :D
    return key

def maptofarm(c):
    assert c in ALPHABET
    return F[ALPHABET.index(c)]

def encrypt(msg, key):
    m64 = base64.b64encode(msg)
    enc, pkey = '', key**5 + key**3 + key**2 + 1
    for m in m64:
        enc += ALPHABET[F.index(pkey * maptofarm(chr(m)))]
    return enc

# 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}')
  •  GF(64) の要素が  F として存在していて、鍵  k は要素のうち14個を(重複ありで)ランダムに選んでかけ合わせたもの

  • 暗号化は  pkey = k^5 + k^3 + k^2 + 1 として、  c_i = BASE64STR\lbrack pkey * m_i \rbrack

  • 暗号文だけが与えられる

実装をミスって? おり、計算がすべて GF(64)上で行われているので pkeyは64通りしかなく、全探索できる

import string


c = "805c9GMYuD5RefTmabUNfS9N9YrkwbAbdZE0df91uCEytcoy9FDSbZ8Ay8jj"

F = list(GF(64))

ALPHABET = string.printable[:62] + '\\='
table = {c:F[ALPHABET.index(c)] for c in ALPHABET}


def decrypt(msg, key):
  pkey = key**5 + key**3 + key**2 + 1
  kinv = pkey**(-1)
  m = ''
  for c in msg:
    m += ALPHABET[F.index(table[c] * kinv)]
  return m

for k in F:
  try:
    print( decrypt(c, k) )
  except:
    pass