[목차]

 

 

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()
728x90

+ Recent posts