반응형

1. 문제

해빈이는 준규에게 메세지를 받았다. 준규는 세계 최고 수준의 암호학자이기 때문에 해빈이에게 암호로 메세지를 보낸다. 이번에 준규는 One Time Pad(OTP) 암호화 방식을 사용하기로 했다. 준규는 OTP방식을 제대로 적용하면 절대 해독할 수 없다는 것을 알기 때문에, 해빈이가 해석할 수 있도록 몇 가지 힌트를 같이 보내기로 했다.

준규는 메세지에 항상 영소문자, 온점('.'), 공백 (' ', ASCII코드 32)만 쓴다. 그리고 key값으로는 항상 '0'부터 '9'까지의 숫자만 쓴다. 이 사실을 알고 있는 해빈이는 이를 이용해 메세지에 있는 온점과 공백의 위치를 알 수 있다는 것을 깨닫고, 당신에게 프로그램으로 만들어달라고 부탁했다.

준규가 이런 메세지를 보낸 게 한두 번이 아니기 때문에 해빈이는 OTP 암호화 방식을 알고 있다. 예를 들어 "0120123"을 key로 사용해서 "abc efg"라는 문자열을 암호화하면 아래와 같다.

abc def
0120123
61 62 63 20 65 66 67
30 31 32 30 31 32 33
51 53 51 10 54 54 54
Start ASCII hexadecimal excrypted message

먼저 key와 메세지 원문을 ASCII 인코딩을 사용해 16진수로 변환한다. 그리고 변환한 key와 원문을 각각 차례대로 XOR 연산한다. 그 결과가 암호화 된 메세지이다.

 

2. 입력

입력에 첫 줄에는 암호화 된 메세지의 길이인 정수 N (1 ≤ N ≤ 1000)이 주어진다.

다음 줄에는 암호화 된 메세지가 N개의 16진수 정수로 주어진다. 이 수는 0(10진수) 이상 127(10진수) 이하이다.

7
51 53 51 10 54 54 54

 

7
53 53 51 54 54 51 10

 

3. 출력

N개의 문자를 한 줄에 출력한다. 만약 i번째 글자가 문자라면 '-'를, 아니라면 '.'을 출력한다.

---.---

 

-----.

 

4. 코드

import sys

input = sys.stdin.readline
n = int(input())
origins = " ."
keys = "0123456789"

# origins과 keys를 아스키코드로 변환 후 16진수로 표현했다.
hex_o, hex_k = origins.encode('ascii').hex(), keys.encode('ascii').hex()

# hex_o와 hex_k를 2자리씩 잘라 배열을 만들었다.
o_list = [int(hex_o[i:i + 2], 16) for i in range(0, len(hex_o), 2)]
k_list = [int(hex_k[i:i + 2], 16) for i in range(0, len(hex_k), 2)]

not_list = []

for i in range(len(origins)):
  for j in range(len(keys)):
    # xor 연산 후 16진수로 표현했다.
    x = str(hex(o_list[i] ^ k_list[j]))
    # x를 다시 정수형태로 표현했다.
    not_list.append(int(x, 16))

message = list(input().split())

for msg in message:
  if int(msg, 16) in not_list:
    print('.', end="")
  else:
    print('-', end="")

 

5. 풀이설명

입력값 n을 입력받는다.

 

② 공백과 "."으로 이루어진 origins와 0~9로 이루어진 keys를 선언한다.

 

origins와 keys를 아스키코드로 변환 후 16진수로 표현하여 hex_o와 hex_k에 대입한다.

 

④ hex_o와 hex_k를 2자리씩 잘라 o_list와 h_list 배열을 생성한다.

 

⑤ 숫자가 아닌 배열 암호키를 넣은 not_list를 빈배열로 선언한다.

 

⑥ orings와 keys로 중복 for문을 실행하는데 o_list[i]와 k_list[j]를 xor 연산 후 16진수로 변경하여 x에 대입한다.

 

⑦ x를 다시 정수형으로 변환하여 not_list에 추가한다.

 

⑧ 입력값 massage를 배열로 입력받는다.

 

⑨ message로 반복문을 실행하는데 msg를 16진수로 표현한 수가 not_list에 포함되면 . 아니면 -를 결과값으로 출력한다.

 

6. 느낀점

아스키 코드 변환, 16진수 변환, 배열 자르기 등 해당 문제를 통해 파이썬에서 제공하는 여러 함수를 배우게 되었다.

반응형

+ Recent posts