본문 바로가기

Games/CTF

Whitehat RSA Signing

2013 화이트햇 콘테스트 예선문제 中 RSA Signing ...


RSA 알고리즘은 아래와 같다.

Choose p = 3 and q = 11

Compute n = p * q = 3 * 11 = 33

Compute φ(n) = (p - 1) * (q - 1) = 2 * 10 = 20

Choose e such that 1 < e < φ(n) and e and n are coprime. Let e = 7

Compute a value for d such that (d * e) % φ(n) = 1. One solution is d = 3 [(3 * 7) % 20 = 1]

Public key is (e, n) => (7, 33)

Private key is (d, n) => (3, 33)

The encryption of m = 2 is c = 27 % 33 = 29

The decryption of c = 29 is m = 293 % 33 = 2


결론은 RSA 가 Homogeneous 임을 이용하여 임의의 Signing 결과를 만들어내는

뭔가 매우 배울점있는 그런거였는데 기억이 잘 안난다... 나중에 다시 풀어봐야겠다.



from Config import Config

from AesUtils import AesUtils

from RsaUtils import RsaUtils

from Crypto.PublicKey import RSA

import md5


IDX_LEN = 4

DATA_LEN = 128


def s2i(s):

  res = 0

  for i in range(len(s)):

    res = (res << 8) | ord(s[i])

  

  return res


def i2s(s):

  res = ""

  while s > 0:

    res = chr(s & 0xFF) + res

    s >>= 8


  return res


class ClientHandler(object):

  def __init__(self, config_path):

    self.forbidden_strings = ['FLAG']

    self.config = Config(config_path)

    pass


  def sign(self, rsa_key, data):

    n = getattr(rsa_key,'n')

    

    data = i2s(s2i(data) % n)


    is_contain_forbidden_str = False

    for forbidden_string in self.forbidden_strings:

      if data.find(forbidden_string) != -1:

        is_contain_forbidden_str = True


    if is_contain_forbidden_str:

      return None

    

    return rsa_key.decrypt(data)


  def handle(self, socket, address):

    socket.send("""Welcome to the A.I. Automatic RSA Signing System\n""")


    rsa_key = RSA.generate(1024)

    n = getattr(rsa_key,'n')

    socket.send('modulo = ' + hex(n)[:-1])


    while True:

      cmd = socket.recv(DATA_LEN)

    

      if len(cmd) == 0:

        break


      socket.send('[ INFO] Processing commands')

      if   cmd[:4] == "SIGN":

        data = socket.recv(DATA_LEN)

        signed_data = self.sign(rsa_key, data)


        if signed_data is None:

          socket.send('[ERROR] Sign failed\n')

          socket.close()

        else:

          socket.send('[ INFO] Sign success\n')

          socket.send(signed_data)


      elif cmd[:4] == "FLAG":

        signed_data = socket.recv(DATA_LEN)

        decoded_data = rsa_key.encrypt(signed_data, "")[0]

        

        if decoded_data == cmd:

          socket.send('[ INFO] FLAG = ' + self.config.flag + '\n')

        else:

          socket.send('[ERROR] Permission denied\n')


      elif cmd[:4] == "PRNT":

        signed_data = socket.recv(DATA_LEN)

        decoded_data = rsa_key.encrypt(signed_data, "")[0]

        

        if decoded_data == cmd:

          socket.send('[ INFO] DATA = ' + i2s(decoded_data) + '\n')

        else:

          socket.send('[ERROR] Permission denied\n')


      else:

        socket.send('[ERROR] No commands')

        socket.close()



'Games > CTF' 카테고리의 다른 글

PHDays 2014 miXer  (0) 2014.01.27
PHDays 2014 FreeBDSM  (0) 2014.01.27
HDCON2013 final cft2  (10) 2013.10.31
Whitehat Contest - Pybox  (5) 2013.09.23
DEFCON 2013 penser writeup  (0) 2013.06.18