[목차]
1. 메세지 복호화 문제 풀기
2. 주상 전치 암호의 암호화/복호화가 같은지 테스트 하는 프로그램 만들기
3. 파일을 입력 받아 주상 전치 암호화 또는 복호화 후 그 내용을 다시 파일에 저장하기
4. 아핀 암호의 암복호화 프로그램 코딩
[문제] 다음 암호화된 메세지를 복호화 하시오.
다음 문제는 https://www.wechall.net(War Game)에서 제공되고 있는 문제 중 하나이다.
(주어진 조건)
* 전치 암호(Trasposition Cipher)
ciphertext = "oWdnreuf.lY uoc nar ae dht eemssga eaw yebttrew eh nht eelttre sra enic roertco drre . Ihtni koy uowlu dilekt oes eoyrup sawsro don:wi ddfarappso.a" |
(힌트)
Wonderful. You .....
■ 코드 1
ciphertext = "oWdnreuf.lY uoc nar ae dht eemssga eaw yebttrew eh nht eelttre sra enic roertco drre . Ihtni koy uowlu dilekt oes eoyrup sawsro don:wi ddfarappso.a"
# 0 -> 1
# 1 -> 0
# 2 -> 3
# 3 -> 2
# 4 -> 5
# 5 -> 4
plaintext = [''] * len(ciphertext)
for n ,ch in enumerate(ciphertext):
if n % 2 == 0 :
plaintext[n+1] = ch
elif n % 2 == 1 :
plaintext[n-1] = ch
print(''.join(plaintext))
코드2
ciphertext = "oWdnreuf.lY uoc nar ae dht eemssga eaw yebttrew eh nht eelttre sra enic roertco drre . Ihtni koy uowlu dilekt oes eoyrup sawsro don:wi ddfarappso.a"
print(ciphertext)
plaintext = ''
loop_num = int(len(ciphertext)/2) # 74
for i in range(loop_num):
plaintext = plaintext + ciphertext[1] + ciphertext[0]
ciphertext = ciphertext[2:]
print(plaintext)
코드3
ciphertext = "oWdnreuf.lY uoc nar ae dht eemssga eaw yebttrew eh nht eelttre sra enic roertco drre . Ihtni koy uowlu dilekt oes eoyrup sawsro don:wi ddfarappso.a"
print(ciphertext)
cipher_list = list(ciphertext)
plaintext = [''] * len(ciphertext)
for num, char in enumerate(cipher_list):
if num % 2 == 0:
plaintext[num+1] = char
elif num % 2 == 1:
plaintext[num-1] = char
print(''.join(plaintext))
[주상 전치 암호의 암호화/복호화가 같은지 테스트 하는 프로그램 만들기]
프로그램을 테스트 하는 프로그램밍
입력 평문의 랜덤화
암호화/복호화 확인
암호화/복호화 성능 측정
# 전치 암호 테스트 프로그램 - lst version # # (0) 준비 : transpositionEncrypt.py, transpositionDecrypt.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] |
transpositionTest.py
#!/usr/bin/python3
#
# 전치 암호 테스트 프로그램 - lst version
#
# (0) 준비 : transpositionEncrypt.py, transpositionDecrypt.py
# (1) 입력 : 임의의 길이의 임의의 문자열
# (2) 출력 : 암호화, 복호화된 메세지가 같은지 출력
# (3) 기능 : 입력 메세지를 압호화, 복호화하고 입력메세지와 복호화된 메세지가 같은지 확인
# * 입력에 대한 Random 화
# * 암호화/복호화 확인
# * 암호화/복화화 성능
import random
import sys
import transpositionEncrypt
import transpositionDecrypt
def main():
random.seed(42) # 무작위 랜덤 함수의 초기화를 위한 시드값을 상수로 설정 한다.
for i in range(20): # 20회 테스트 한다.
# 테스트용 무작위 메세지를 생성한다.
# 생성된 메세지는 길이가 임의의 값이 될것이다.
message = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' * random.randint(4, 40)# 네글자에서 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 = transpositionEncrypt.encrypt_message(key, message)
decrypted = transpositionDecrypt.decrypt_message(key, encrypted)
# 원래 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()
버전2
import random
import sys
try:
import transpositionEncrypt
import transpositionDecrypt
except Exception as e:
sys.exit('Error:', e)
def main():
random.seed(35)
for i in range(20):
messages = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' * random.randint(4, 40)
messages = list(messages)
random.shuffle(messages)
messages = ''.join(messages)
print('Test #%s: |%s|' % (i + 1, messages[:50]))
for key in range(1, int(len(messages) / 2)):
encrypted = transpositionEncrypt.encrypt_transposition(messages, key)
decrypted = transpositionDecrypt.decrypt_transposition(encrypted, key)
if messages != decrypted:
print('Mismatch with key %s and plaintext %s' % (key, messages))
print('Decrypted as: ' + decrypted)
sys.exit(2)
print('Transposition cipher test passwd.')
if __name__ == '__main__':
main()
[파일을 입력 받아 주상 전치 암호화 또는 복호화 후 그 내용을 다시 파일에 저장하기]
디스크에서 파일을 읽거나 쓰는 프로그램을 작성.
(준비) frankenstein.txt, transpositionEncrypt.py, transpositionDecrypt.py
# vi transpostionFileChipher.py
# 전치 파일 암호 암호화/복호화 - 1st version # # (0) 준비: frankenstein.txt, transpositionEncrypt.py, transpositionDecrypt.py # (1) 입력: 파일이름(EX: frankenstein.txt) # (2) 출력: 암호화된 파일(EX: frankenstein.encrypted.txt) # (3) 기능: # * 파일을 입력 받아 암호화 또는 복호화 수행한 후 그 내용을 다시 파일로 생성한다. |
import os
import sys
import time
try:
import transpositionEncrypt
import transpositionDecrypt
except Exception as e:
sys.exit('Error:', e)
def main():
input_filename = 'frankenstein.txt'
mykey = 10
startime = time.time()
enc_file = encryption_transposition_file(input_filename, mykey)
dec_file = decryption_transposition_file(enc_file, mykey)
endtime = time.time()
print("Total time:", endtime - startime)
def decryption_transposition_file(efile, key):
# input: file(efile), int(key)
# output: file(dfile)
# function:
if not os.path.exists(efile):
print('The file %s does not exist. Quiting' % efile)
sys.exit(1)
outputfilename = file_conversion_result(efile, 'decrypted')
if os.path.exists(outputfilename):
print('This is overwrite the file %s. (C)ontinue or (Q)uit?' % outputfilename)
response = input('> ')
if not response.lower().startswith('c'):
sys.exit(2)
fd = open(efile, 'rt')
content = fd.read()
fd.close()
decrypted = transpositionDecrypt.decrypt_transposition(content, key)
fd = open(outputfilename, 'wt')
fd.write(decrypted)
fd.close()
return outputfilename
def encryption_transposition_file(filename, key):
if not os.path.exists(filename):
print('The file %s does not exist. Quiting' % filename)
sys.exit(1)
outputfilename = file_conversion_result(filename, 'encrypted')
if os.path.exists(outputfilename):
print('This is overwrite the file %s. (C)ontinue or (Q)uit?' % outputfilename)
response = input('> ')
if not response.lower().startswith('c'):
sys.exit(2)
fd = open(filename)
content = fd.read()
fd.close()
enc_msg = transpositionEncrypt.encrypt_transposition(content, key)
fd = open(outputfilename, 'wt')
fd.write(enc_msg)
fd.close()
return outputfilename
def file_conversion_result(file, edstr):
# input : file(ex: frankenstein.txt)
# output: file(ex: frankenstein.encrypted.txt)
# function:
tmp_list = file.split('.')
tmp_list.insert(-1, edstr)
return '.'.join(tmp_list)
if __name__ == '__main__':
main()
[아핀 암호의 암복호화 프로그램 코딩]
C = (P * K1 + K2) mod len(symbols)
(조건) K1, K2에 대한 몇가지 조건
K1 = 1 이면 안된다. 곱셈하는 의미가 없어지기 때문이다.
K2 = 0 이면 안된다. 덧셈하는 의미가 없어지기 때문이다.
K2 < len(symbols)
곱셈 암호 방식은 K1, len(symobs)는 서로소 관계이어야 한다.
(ex: gcd(K1, len(symbols) == 1)
암호화 과정:
(ㄱ) 평문을 K1으로 곱셈
(ㄴ) K2를 더함
(ㄷ) 심볼 집합 크기로 나머지 연산
■ 아핀 암호의 복호화
P = {(C - K2) * K1-1} mod len(symbols)
(조건) K1, K2에 대한 몇가지 조건(암호화 조건과 같다.)
K1 = 1 이면 안된다. 곱셈하는 의미가 없어지기 때문이다.
K2 = 0 이면 안된다. 덧셈하는 의미가 없어지기 때문이다.
K2 < len(symbols)
곱셈 암호 방식은 K1, len(symobs)는 서로소 관계이어야 한다.
(ex: gcd(K1, len(symbols) == 1)
복호화 과정:
(ㄱ) 암호문에서 K2를 뺀다.
(ㄴ) K1의 모듈러 역수 연산
(ㄷ) 심볼 집합 크기로 나머지 연산
■ 아핀 암호의 키의 범위
왜 K2 < len(symbols) 관계이어야 하는가?
다음 실습을 통해 확인한다.
아핀 암호의 K2의 범위는 len(symbols) 이어야 한다. 이것은 K2가 심볼의 크기를 넘게 되면 모듈러 연산 때문에 다시 처음으로 돌아 오게 되기 때문이다.
=> K2 > len(SYMBOLS) - 1
아핀 암호에서 K1과 len(SYMBOLS)는 최대 공약수가 1이어야 한다.
import os
import sys
import random
try:
import cryptomath
except Exception as e:
sys.exit('Error:', e)
SYMBOLS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890 !?.'
def main():
my_message = """A computer would deserve to be called intelligent if it could deceive a human into believing that it was human. -Alan Turing"""
my_key = 2894
enc_msg = encrypt_message(my_message, my_key)
print("Plaintext :", my_message)
print("Ciphertext: ", enc_msg)
dec_msg = decrypt_message(enc_msg, my_key)
print("Decrypted :", dec_msg)
def decrypt_message(msg, key):
key_a, key_b = get_key_parts(key)
check_keys(key_a, key_b, 'decrypt')
# P = ((C - K2) * K1(-1)) mod len(SYMBOLS)
plaintext = ''
for symbol in msg:
#print(symbol)
if symbol in SYMBOLS:
symbol_index = SYMBOLS.find(symbol)
mod_inverse_of_key_a = cryptomath.find_mod_inverse(key_a, key_b)
affine_index = (symbol_index - key_b) * mod_inverse_of_key_a % len(SYMBOLS)
#print(affine_index)
plaintext += SYMBOLS[affine_index]
else:
plaintext += symbol
return plaintext
def encrypt_message(msg, key):
# input : str(msg), int(key)
# output : str(enc_msg)
# function: affine cipher
key_a, key_b = get_key_parts(key)
#print(key_a, key_b)
check_keys(key_a, key_b, 'encrypt')
# * affine cipher : C = (P * K1 + K2) mod len(SYMBOLS)
ciphertext = ''
for symbol in msg:
if symbol in SYMBOLS:
symbol_index = SYMBOLS.find(symbol)
affine_index = (symbol_index * key_a + key_b) % len(SYMBOLS)
#print(symbol, symbol_index)
ciphertext += SYMBOLS[affine_index]
else:
ciphertext += symbol
return ciphertext
def check_keys(key1, key2, mode):
if key1 == 1 and mode == 'encrypt':
sys.exit('Cipher is weak if key A is 1. Choose a different key.')
if key2 == 0 and mode == 'encrypt':
sys.exit('Cipher is weak if key B is 0. Choose a different key.')
if key1 < 0 or key2 > len(SYMBOLS) -1:
sys.exit('Key A must be greater than 0 and key B must be between 0 and %d' % (len(SYMBOLS) - 1))
if cryptomath.gcd(key1, len(SYMBOLS)) != 1:
sys.exit('key A (%s) and the symbol set size (%s) are not relatively prime. Choose a different key.' % (key_a, len(SYMBOLS)))
def get_key_parts(key):
# input : int(key)
# output : int(key1), int(key2)
# funcrion :
key1 = key // len(SYMBOLS)
key2 = key % len(SYMBOLS)
return key1, key2
if __name__ == '__main__':
main()
'정보보안공부 > 정보보안전문과정' 카테고리의 다른 글
정보보안 과정 Day80 : 암호학 5 (0) | 2020.12.30 |
---|---|
정보보안 과정 Day79 : 암호학 4 (0) | 2020.12.29 |
정보보안 과정 Day77 : 암호학 2 (0) | 2020.12.27 |
정보보안 과정 Day 76-2 : 암호학 실습 (0) | 2020.12.23 |
정보보안 과정 Day 76-1 : 암호학 이론 (0) | 2020.12.23 |