티스토리 뷰

오늘 소개 할 암호는 비즈네르 암호(vigenere cipher) 입니다.

비즈네르 암호는 다표식 암호 중에서도 반복키 암호(repeating-key cipher)입니다.

반복키 암호란 단어나 구로 된 키워드(keyword)를 필요한 만큼 반복해 

key로 사용하는 암호입니다.

<비즈네르표 / 출처 : https://ko.wikipedia.org/wiki/비즈네르_암호>

암호문은 모듈로 26에 대해 평문 숫자와 키 숫자를 더한 값으로 나타낼 수있습니다.

평문이 "computer" 키워드가 "dog"인 비즈네르 암호의 예를 살펴봅시다.

키워드 d o g d o g d o
키워드숫자 4 15 7 4 15 7 4 15
평문 c o m p u t e r
평문 숫자 3 15 13 16 21 20 5 18
암호문 g d t t j a i g
암호문숫자 7 4 20 20 10 1 9 7

위의 표처럼 키워드는 필요한 만큼 반복되고 암호문은 모듈러 26에 대해

key와 평문의 숫자를 더한 값입니다.

 

다음은 복호화에 대해 생각해봅시다.

반복키 암호의 주기를 알게되면 같은 키를 사용하는 암호문끼리의 빈도 분석이 가능해집니다 !

암호 주기를 l 문자의 갯수를 n이라고 해봅시다.

각 l열에 n/l 개의 문자가 있는 배열을 생각할 수있습니다.

같은 열에서는 같은 키로 암호화했기 때문에 동시발생지수가 약 0.066일 것이고

무작위로 서로 다른 두 열을 선택하고 각 열에서 문자를 하나씩 뽑는다면

동시발생지수는 약 0.038일 것입니다.

따라서 전체 동시발생지수는 다음과 같이 계산 할 수 있습니다.

주기 l 1 2 3 ... 10↑
동시발생지수 0.066 0.052 0.047 ... 0.038

n의 값이 클때 주기 l에 따른 대략의 동시발생지수의 값으로 주기(l)을 추측할 수도 있습니다.

 

또는 직접 구한 동시발생지수와 위의 식을 같다고 식을 만든 후 

l에 대한 방정식을 풀어 대략의 l의 값을 추측할 수도 있습니다.

 

주기를 구하는 다른 방법에는 카지스키 테스트(kasiski test)가 있습니다.

카지스키 테스트는 반복되는 문자열을 찾는 것에서 출발합니다.

반복 문자열의 각각 첫 문자부터 다음 반복이 나타나기까지 문자의 갯수를 셉니다.

반복되는 문자열의 각격의 공약수가 암호 주기가 될 가능성이 높다고 할 수 있습니다.

왜냐하면 평문에서 반복되는 부분이 반복되는 키를 기준으로 같은 위치에 오면

암호문도 반복되기 때문입니다.

물론 반복되는 문자열에는 반복되는 키가 아닌 우연의 경우가 있을 수도 있습니다.

따라서 어떤 간격을 포함했을 때 주기가 1이 나온다면 그 간격은 검사에 포함하지 말아야 합니다.

 

같은 key를 통해 암호화된 암호문은 일반 텍스트와 같은 빈도를 가지고 있기 때문에

주기를 찾은 후에는 빈도분석법을 통해 key를 찾을 수 있습니다.

 

inputText = []
cipherText = []
coin = [0 for i in range(26)]

def modulo(a,b):
    a = a % b
    return a

def vigenere(inputText,key):
    textLen = len(inputText)
    keyLen = len(key)
    for i in range (0,textLen):
        val = modulo((ord(inputText[i]) - ord("a") + 1) + (ord(key[modulo(i,keyLen)]) - ord("a") + 1),26)
        if(val == 0) :
            cipherText.append('z')
        else:
            cipherText.append(chr(val + ord("a") - 1))

def analysis(inputText):
    textLen = len(inputText)
    for i in range(0,textLen):
        index = ord(inputText[i]) - ord("a")
        coin[index] += 1
    value = 0
    for i in range(0,26):
        value += pow(coin[i]/textLen,2)

    return value

def textPrint(text):
    textLen = len(text)
    for i in range(textLen):
        print(text[i],end='')

if __name__ == "__main__":
    inputText = input("enter plainText : ")
    inputText = inputText.lower()
    inputText = inputText.replace(" ","")
    textLen = len(inputText)

    key = input("enter a key : ")

    coincidence = analysis(inputText)

    print("index of coincidence is " + str(coincidence))

    vigenere(inputText,key)
    print("cipher text : ",end='')
    textPrint(cipherText)

 

비즈네르 암호를 생성하는 코드와

동시발생지수를 계산하는 코드를 작성해 보았습니다.

동시발생지수를 통해서 비즈네르 암호의 주기를 추측해 볼 수 있을 것입니다.

 

오늘도 긴글 읽어주셔서 감사합니다.

부족하거나 틀린부분은 알려주시면 감사하겠습니다.

댓글