암알못의 암호 핥기 - 전치암호

By rls1004 | December 3, 2016

암알못의 암호 핥기 - 전치암호





이번 편에서는 고전 암호 중 전치 암호에 대해 알아보려고 합니다!




1. 전치 암호 : 단순 전치 암호


전치 암호는 평문의 알파벳 순서를 재배치하여 암호화 합니다.

암호화 키가 14352라고 하면 평문인 “ABCDEFG”는 “ADCEBFG”로 암호화됩니다.

이때 복호화 키는 무엇일까요?


암호화 키가 14352 일 때 복호화 키 구하기

[1의 인덱스: 1][2의 인덱스: 5][3의 인덱스: 3][4의 인덱스: 2][5의 인덱스: 4]

복호화 키는 15324


복호화 키인 15324에 의해 암호문인 “ADCEBFG”를 복호화하면 “ABCDEFG”로 복호화됩니다.


역시 문제를 풀어볼까요?


Training: Crypto - Transposition I


oWdnreuf.lY uoc nar ae dht eemssga eaw yebttrew eh nht eelttre sra enic roertco drre . Ihtni koy uowlu dilekt oes eoyrup sawsro don:wm ibirlgeacb.m
(주의! 암호문과 정답은 계속 달라집니다)


어렵지 않은 전치암호인데요, 마침표가 등장하는 첫 번째 문장을 봅시다.


oWdnreuf.lY


문자의 구성들을 보면 단어를 유추할 수 있는데요, Wonderful 이라는 단어가 떠오르네요.


Wonderful이라는 단어를 만들기 위한 복호화키를 생각해보면, 두 글자씩 서로 자리를 바꿔야된다는 것을 금방 알 수 있습니다.

그렇다면 암호화 키와 복호화 키는 둘 다 21이 되겠네요!


'''
WeChall
Training: Crypto - Transposition I
'''

def solve(chip, key):
    chip = list(chip)
    key = list(key)
    mes = ''
    for i in range(len(chip)+len(key)):
        try:
            mes += chip[int(key[i%len(key)])+(i/len(key))*len(key)-1]
        except :
            pass
    return mes

if __name__ == '__main__':
    print "===Transposition==="
    print "> Input Chiper message"
    chip = raw_input('> ')
    print "> Input decrypt key"
    key = raw_input('> ')
    print "[*] "+solve(chip,key)



짧은 키 길이 덕분에 암호화키와 복호화키를 금방 알 수 있었습니다!




2. 전치 암호 : 스키탈리


이전 편에서 스키탈리 암호가 잠깐 등장했는데요, 스키탈리(스키테일, 스키탈레 등 등..) 암호 역시 전치 암호에 속합니다.


# 출처 : 위키백과 ‘스키테일’


스키탈리 암호는 스파르타에서 전쟁터에 나가있는 아군과 소통할 때 사용한 암호입니다.


위 그림에 보이는 원통형의 나무 막대를 스키탈리라고 하고, 이 막대에 양피지를 감아 메세지를 적고 펼치면 암호문이 만들어집니다.


펼쳐진 양피지를 다시 같은 굵기의 스키탈리에 감으면 평문을 읽을 수 있게 됩니다.

스키탈리 암호에서 암호키와 복호키는 스키탈리의 굵기가 되겠네요~


재밌어보이는데 직접 만들어 볼까요??

손으로 만들긴 귀찮으니 컴퓨터에게 시킵시다!


스키탈리 암호를 해독해주는 코드입니다~


'''
Transposition Chiper
Scytale Decrypt Service
'''

#-*- coding: utf-8 -*-

def solve(pigi, key, w):
    key = int(key)
    pigi = list(pigi)
    mes = ''
    for i in range((len(pigi)+key-1)/key):
        tmp = i*key+w%key
        if tmp < len(pigi):
            mes += pigi[tmp]
    return mes

def scytale(mes):
    line1 = "  ┌─┐"
    line2 = "┌─┤ ├"
    line3 = "│ │"
    line4 = "└─"
    line5 = ""
    for i in range(len(mes)):
        if i < len(mes)-1:
            line2 += "─┬"
            line4 += "┴─"
        line3 += mes[i:i+1]
        line3 += "│"
        line5 += "  "

    line2 += "─┐"
    line3 += " │"
    line4 += "┤ ├─┘"
    line5 += "└─┘"

    print line1
    print line2
    print line3
    print line4
    print line5

if __name__ == "__main__":
    print "===Scytale Service==="
    print "[*] Input Crypto MSG"
    pigi = raw_input('> ')
    print "[*] Input Key"
    key = raw_input('> ')

    select = ''
    w = 0
    while True:
        if len(pigi) < int(key):
            print "Invalid key"
            break

        mes = solve(pigi, key, w)
        scytale(mes)
        print "1) wheel up [w]"
        print "2) quit     [q]"
        select = raw_input('> ')
        if select == 'w':
            w += 1
        elif select == 'q':
            break
        else:
            print "Wrong Select"


-- coding: utf-8 --


파이썬의 기본 인코딩은 ascii 인데요,

미관을 위해 특수문자를 출력할 것이기 때문에 인코딩이 utf-8이라고 알려주는 코드를 꼭 추가해주어야 합니다.


핵심이 되는 코드는 solve 함수의 for문 입니다.


코드에 대한 설명을 드리자면,

전체 문장을 키 값만큼의 길이를 갖도록 블록으로 나누고,

각 블록에서 0번째 값들을 차례로 모두 이어붙이고, 이어서 1번째 값들을 모두 이어붙이는 형태입니다.


[Slc i] [cerSc] [y yee] [tDpr ] [aetv]

0 번째 값들 : Scyta

1 번째 값들 : le De

2 번째 값들 : crypt

3 번째 값들 : Serv

4 번째 값들 : ice


이것을 합치면 평문!

이제 확인해볼까요? :)



이 프로그램에서의 키 값은 스키탈리의 한 지름에 들어갈 수 있는 문자 수를 의미하도록 했습니다.

암호문을 입력하고 키를 입력하면 스키탈리에 암호문을 감아 평문을 볼 수 있습니다.


키를 모를 땐 어떻게 할까요??

키 값을 증가시켜가며 알아볼 수 있는 평문이 나올 때까지 반복하면 될 것 같습니다.


그럼, 다음의 스키탈리 암호문을 해독 해 볼까요? :)


스키탈리 암호 해독 해보기

hmiien jmieyso nnmga




3. 전치 암호 : Rail Fence


Rail Fence 암호는 깊이에 따라 지그재그 모양으로 문자를 배치하여 암호화합니다.

여기서 암호화 키와 복호화 키는 깊이가 됩니다.


  • 깊이가 2인 Rail Fence 암호


  • 깊이가 3인 Rail Fence 암호


암호화 방법은 위처럼 그림을 그리면 쉽게 할 수 있는데요, 복호화 방법은 어떻게 될까요?


깊이가 3인 Rail Fence 암호

RFep | alecCyt | inro


깊이가 3이면 3개의 블록으로 나눌 수 있습니다.

앞에서 부터 첫 번째, 두 번째, 세 번째 블록이라고 하면

1 > 2 > 3 > 2 의 순서를 반복하여 알파벳을 하나씩 가져오면 됩니다.


여기서 주의해야 할 것은 각 블록의 크기입니다.

막상 코드를 짜려고 보니 각 블록의 크기를 계산해야 했습니다.

저는 수학 공식을 짜보려고 노력했지만.. 결국 암호화 순서를 따라가며 각 블록의 크기를 카운트했습니다.


아래는 그것을 적용한 복호화 코드입니다!


'''
Transposition Chiper
Rail Fence Decrypt Service
'''

def solve(crypt, key):
    key = int(key)
    crypt = list(crypt)
    mes = ''

    index = []
    block_size = []

    idx = 0
    flag = 0

    # block size
    for i in range(len(crypt)):
        if len(block_size) <= idx:
            block_size.append(1)
        else:
            block_size[idx] += 1

        if idx == key-1:
            flag = 1
        elif idx == 0:
            flag = 0

        if flag == 1:
            idx -= 1
        elif flag == 0:
            idx += 1

    # set index
    for i in range(len(block_size)):
        index.append(0)

    idx = 0
    flag = 0

    # get char
    for i in range(len(crypt)):

        tmp = 0

        for j in range(idx):
            tmp += block_size[j]

        tmp += index[idx]
        index[idx] += 1

        mes += crypt[tmp]       

        if idx == key-1:
            flag = 1
        elif idx == 0:
            flag = 0

        if flag == 1:
            idx -= 1
        elif flag == 0:
            idx += 1

    return mes

if __name__ == "__main__":
    print "===Rail Fence Service==="
    print "[*] Input Crypto MSG"
    crypt = raw_input('> ')
    print "[*] Input Key"
    key = raw_input('> ')
    print "[*] "+solve(crypt,key)


다시 두 번째 블록으로 돌아가야 하는데, 이것을 나타내는 값이 flag 변수의 값입니다.

증가해야할 타이밍인지 감소해야할 타이밍인지를 알려주는 값입니다.



잘 작동 하네요~


키 값인 깊이를 모른다면 어떻게 할까요??

스키탈리 암호의 경우처럼 깊이를 점차 늘려가며 알아볼 수 있는 평문이 나올 때까지 반복하면 될 것 같습니다.




마무리


  • 단순 전치 암호

    1. 문자의 순서를 재배치

    2. 암호문과 평문이 같은 문자 조합을 갖는다.


  • 예시 : 스키탈리

    1. 스키탈리라는 원통을 이용한 암호화 및 복호화

    2. 스키탈리의 두께를 알면 복호화가 가능하다.


  • * 예시 : Rail Fence

    1. 깊이 만큼 지그재그로 문자를 배치하여 암호화

    2. 깊이를 알면 복호화가 가능하다.




지금까지 고전 암호 중 전치 암호에 대해 알아봤습니다.


과거의 치환/전치 암호들은 해독이 쉬웠지만 점차 암호화 방식이 복잡해지며 해독을 어렵게하는 방식들이 나타났습니다.


한 가지 방법을 여러번 시도하여 암호화 하거나 여러가지 방법을 섞어 암호화하는 방식들도 있는데요,

암호에 대해 좀 더 내공이 쌓인다면 또 둘러보도록 합시다:D


comments powered by Disqus