[실습] 전치 암호(Transposition Cipher)
단순 전치 암호
= 주상 전치 암호
= 열 방향 전치 암호
주상 전치 암호(열 방향 전치 암호, 단순 전치 암호) 만들기
전치 암호의 종류들
- 단순 전치 암호
- 레일 펜스(Rail Fence)
- 경로(Route) 암호
- 가로장 암호
- 미즈코우스키(Myszkowski) 전치 암호
- 분할된 전치 암호
- 기타
간단한 전치 암호 중 하나인 "열 방향(columnar) 전치 암호"에 대한 프로그램을 만들어 보자.
(예) 주상 전치 암호 - 암호화
평문 : "Common sense is not so common." : 30글자
키 : 8
암호문 : "Cenoonommstmme oo snnio. s s c" : 30글자
transpositionEncrypt.py
# 주상 전치 암호화 - 1st version # # (1) 입력 : 평문 메세지 (Input: Common sense is not so common.) # (2) 출력 : 주상 전치 암호화/복호화 후 메세지 (Ouput: |Cenoonommstmme oo snnio. s s c|) # (3) 기능 : # * 평문 메세지를 입력으로 받아서 # * 주상 전치 암호화 알고리즘을 이용하여 암호화/복호화 한다. # (4) [참고] 전치 암호화 과정 # 1) messages와 key의 문자 수를 센다. # 2) 키와 같은 개수의 상자를 한줄에 그린다.(예: 키가 8개면 상자 8개) # 3) 왼쪽에서 오른쪽으로 상자를 채우고 상자 한개에 글자 한개를 넣는다. # 4) 문자가 상자 끝에 이르면 상자의 줄을 한 줄 더 그린다. # 5) 마지막 문자까지 오면 마지막 행에 있는 사용하지 않은 상자는 칠해 둔다. # 6) 왼쪽 상단부터 시작해 각 열을 내려가면서 문자를 쓴다. # 열의 가장 아래에 이르면 오른쪽의 다음 열로 이동한다. # 지운 상자는 건너뛴다. 이것이 암호문이 된다. |
암호시스템 : 주상 전치 암호 키 : 8 입력 평문 : Common sense is not so common. 출력 암호문: ? |
def main():
mymsg = "Common sense is not so common."
mykey = 8
print("Plaintext : |%s|" %mymsg)
myencrypted = transposition_cipher(mymsg, mykey)
print("Encrypted : |%s| " %myencrypted)
def transposition_cipher(msg, key):
# input: str(msg), int(key)
# output: str(encrypted)
# function:
# * transposition cipher with key = 8
encrypted = [''] * key
for n, c in enumerate(msg):
str_index = n % key
encrypted[str_index] += c
return ''.join(encrypted)
if __name__ == '__main__':
main()
(예) 주상 전치 암호 - 복호화
암호문 : "Cenoonommstmme oo snnio. s s c" : 30글자
키 : 8
평문 : "Common sense is not so common." : 30글자
(조건) msg = "....", key = 8
메세지 전체 크기: 30
전체 박스의 크기: 4 * key = 32
math.ceil(30 / 8) = 4
블랙 박스의 크기: 32 - 30 = 2
블랙 박스의 index 값?
(32 - 1) - (i * 4)
문자열의 특정 index안에 ^ 문자 넣기
* str = str[:num] + ^ + str[num:]
transpositionDecrypt.py
# 주상 전치 복호화 - 1st version # # (1) 입력 : 평문 메세지 (Input: Common sense is not so common.) # (2) 출력 : 주상 전치 암호화/복호화 후 메세지 (Ouput: ) # (3) 기능 : # * 평문 메세지를 입력으로 받아서 # * 주상 전치 암호화 알고리즘을 이용하여 암호화/복호화 한다. # (4) [참고] 전치 암호화 과정 # 1) messages와 key의 문자 수를 센다. # 2) 키와 같은 개수의 상자를 한줄에 그린다.(예: 키가 8개면 상자 8개) # 3) 왼쪽에서 오른쪽으로 상자를 채우고 상자 한개에 글자 한개를 넣는다. # 4) 문자가 상자 끝에 이르면 상자의 줄을 한 줄 더 그린다. # 5) 마지막 문자까지 오면 마지막 행에 있는 사용하지 않은 상자는 칠해 둔다. # 6) 왼쪽 상단부터 시작해 각 열을 내려가면서 문자를 쓴다. 열의 가장 아래에 이르면 오른쪽의 다음 열로 이동한다. # 지운 상자는 건너뛴다. 이것이 암호문이 된다. |
암호 시스템: 주상 전치 암호 입력 암호문: Cenoonommstmme oo snnio. s s c 키 : 8 출력 평문 : ? ■ 올림 import math math.ceil(len(messages)/key) ■ 올림, 내림, 반올림 math.ceil() : 올림, math.floor(), 내림, math.round() : 반올림 |
import math
def main():
mymsg = "Common sense is not so common."
mykey = 8
print("Plaintext : |%s|" %mymsg)
myencrypted = transposition_cipher_encrypt(mymsg, mykey)
print("Encrypted : |%s| " %myencrypted)
mydecrypted = transposition_cipher_decrypt(myencrypted, mykey)
print("Decrypted : |%s| " %mydecrypted)
def transposition_cipher_decrypt(msg, key):
# 메시지 전체 크기 : 30
msg_total_size = len(msg)
# 리스트 인덱스 값 : 4
list_index = math.ceil(msg_total_size / key)
# 블랙 박스의 크기 : 2
array_total_size = list_index * key
black_box_size = array_total_size - msg_total_size
# 블랙 박스 리스트 : [27, 31]
black_box_list = []
for i in range(black_box_size):
black_box_index = (array_total_size - 1) - (i * list_index)
black_box_list.append(black_box_index)
black_box_list.reverse()
# 메세지 안에 특수문자(^) 집어 넣기 : .....^...^
for j in black_box_list:
msg = msg[:j] + '^' + msg[j:]
# 복호화 목록을 담은 리스트
decrypted_list = [''] * list_index
# 메세지를 받아서 복호화 리스트안에 나누어 담기
for n, k in enumerate(msg):
decrypted_list_index = n % list_index
decrypted_list[decrypted_list_index] += k
# 리스트 안의 스트링을 붙이고 msg_total_size 만큼만 자르기
decrypted = ''.join(decrypted_list)
decrypted = decrypted[:msg_total_size]
return decrypted
def transposition_cipher_encrypt(msg, key):
# input: str(msg), int(key)
# output: str(encrypted)
# function:
# * transposition cipher with key = 8
encrypted = [''] * key
for n, c in enumerate(msg):
str_index = n % key
encrypted[str_index] += c
return ''.join(encrypted)
if __name__ == '__main__':
main()
[실습] 전치 암호 테스트 프로그램 - Transposition Cipher Test
주상 전치 암호의 암호화/복호화가 같은지 테스트 하는 프로그램 만들기
프로그램을 테스트 하는 프로그램밍 기법을 소개한다.
- 입력 평문의 랜덤화
- 암호화/복호화 확인
- 암호화/복호화 성능 측정
transpositionTest.py
# 전치 암호 테스트 프로그램 - lst version # # (0) 준비 : transposition.py # (1) 입력 : 임의의 길이의 임의의 문자열 # (2) 출력 : 암호화, 복호화된 메세지가 같은지 출력 # (3) 기능 : 입력 메세지를 압호화, 복호화하고 입력메세지와 복호화된 메세지가 같은지 확인 |
[참고 사항] ■ random 모듈 import 방법과 .seed(), .randint(), .suffile() method 설명 import random random.seed(42) random.randint(4, 40) random.shuffle(list) for i in range(int(random.randint(message/2))) ; print(i) |
■ random.seed(42) 의미 import random numbers = [] for i in range(20): numbers.append(random.randint(1, 10)) print(numbers) 여러번 실행 시켜 본다. [5, 9, 8, 3, 6, 2, 3, 9, 9, 1, 7, 4, 1, 8, 10, 2, 7, 10, 1, 7] [8, 4, 8, 1, 2, 5, 2, 2, 6, 5, 3, 1, 2, 5, 9, 9, 9, 10, 7, 3] [10, 9, 1, 5, 2, 10, 1, 2, 9, 4, 9, 3, 9, 4, 1, 10, 5, 10, 4, 7] import random random.seed(42) numbers = [] for i in range(20): numbers.append(random.randint(1, 10)) print(numbers) 여러번 실행 시켜 본다. [2, 1, 5, 4, 4, 3, 2, 9, 2, 10, 7, 1, 1, 2, 4, 4, 9, 10, 1, 9] [2, 1, 5, 4, 4, 3, 2, 9, 2, 10, 7, 1, 1, 2, 4, 4, 9, 10, 1, 9] [2, 1, 5, 4, 4, 3, 2, 9, 2, 10, 7, 1, 1, 2, 4, 4, 9, 10, 1, 9] |
import random
import sys
import transposition
def main():
random.seed(42) # 무작위 랜덤 함수의 초기화를 위한 시드값을 상수로 설정 한다.
for i in range(20): # 20회 테스트 한다.
# 테스트용 무작위 메세지를 생성한다.
# 생성된 메세지는 길이가 임의의 값이 될것이다.
message = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' * random.randint(4, 40)
# plaintext 문자열을 뒤섞기 위해 리스트를 만든다.
message = list(message)
# 리스트의 요소 뒤섞기
random.shuffle(message)
# 리스트를 다시 문자열로 전환
message = ''.join(message)
print("Test #%s: |%s|" % (i+1, message[:50]))
# 각 message에 대해 가능한 모든 키 값을 확인한다.
for key in range(1, int(len(message)/2)):
encrypted = transposition.transposition_cipher_encrypt(message, key)
decrypted = transposition.transposition_cipher_decrypt(encrypted, key)
# 원래 message의 복호화된 message가 틀리면 에러 메세지를 출력하고 종료
if message != decrypted:
print('Mismatch with key %s and plaintext %s' % (key, message))
print('Decrypted as: ' + decrypted)
sys.exit(1)
print('Transposition cipher test passed.')
if __name__ == '__main__':
main()
[실습] 파일을 입력 받아 전치 암호화 또는 복호화 수행후 파일에 저장하기
파일을 입력 받아 주상 전치 암호화 또는 복호화 후 그 내용을 다시 파일에 저장하기
디스크에서 파일을 읽거나 쓰는 프로그램을 작성하는 방법을 다룬다.
(준비) frankenstein.txt, transposition.py
# 전치 파일 암호 암호화/복호화 - 1st version # # (0) 준비: frankenstein.txt, transpositionEncrypt.py, transpositionDecrypt.py # (1) 입력: 파일이름(EX: frankenstein.txt) # (2) 출력: 암호화된 파일(EX: frankenstein.encrypted.txt) # (3) 기능: # * 파일을 입력 받아 암호화 또는 복호화 수행한 후 그 내용을 다시 파일로 생성한다. |
transpostionFileCipher.py
import random
import sys
import transposition
def main():
random.seed(42) # 무작위 랜덤 함수의 초기화를 위한 시드값을 상수로 설정 한다.
for i in range(20): # 20회 테스트 한다.
# 테스트용 무작위 메세지를 생성한다.
# 생성된 메세지는 길이가 임의의 값이 될것이다.
message = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' * random.randint(4, 40)
# plaintext 문자열을 뒤섞기 위해 리스트를 만든다.
message = list(message)
# 리스트의 요소 뒤섞기
random.shuffle(message)
# 리스트를 다시 문자열로 전환
message = ''.join(message)
print("Test #%s: |%s|" % (i+1, message[:50]))
# 각 message에 대해 가능한 모든 키 값을 확인한다.
for key in range(1, int(len(message)/2)):
encrypted = transposition.transposition_cipher_encrypt(message, key)
decrypted = transposition.transposition_cipher_decrypt(encrypted, key)
# 원래 message의 복호화된 message가 틀리면 에러 메세지를 출력하고 종료
if message != decrypted:
print('Mismatch with key %s and plaintext %s' % (key, message))
print('Decrypted as: ' + decrypted)
sys.exit(1)
print('Transposition cipher test passed.')
if __name__ == '__main__':
main()
'현대 암호학' 카테고리의 다른 글
[현대 암호학] 03. 실습(4) (0) | 2021.06.22 |
---|---|
[현대 암호학] 03. 실습(3) (0) | 2021.06.22 |
[현대 암호학] 03. 실습(1) (0) | 2021.06.21 |
[현대 암호학] 03-4. 전치 암호와 치환 암호 (0) | 2021.06.21 |
[현대 암호학] 03-2. 단일 치환 암호 (0) | 2021.06.18 |