본문 바로가기
Sejong University/Symmetric-key cryptography

Classic Cipher

by reindeer002 2022. 4. 23.
728x90
import random as r #key를 만들기 위한 랜덤 모듈
import copy as c #LFSR함수에서 key데이터를 복사하기 위한 모듈

def capital(alpha): #대문자 검사를 위한 함수
    if alpha >= ord('A') and alpha <= ord('Z'): #대문자라면
        return 1 #1반환
    else: #대문자가 아니라라면
        return 0 #0반환

def shift_encrypt(key, msg): #쉬프트 암호화 함수
    length = len(msg) #평문의 길이
    ctx = '' #암호문
    for i in range(0, length): #평문의 문자 개수만큼 반복
        if capital(ord(msg[i])) == 1: #대문자라면
            ctx += chr(ord('A') + ((ord(msg[i]) - ord('A')) + key) % 26) #대문자 기준 key만큼 문자를 shift
        else: #소문자라면
            ctx += chr(ord('a') + ((ord(msg[i]) - ord('a')) + key) % 26) #소문자 기준 key만큼 문자를 shift
    return ctx #암호문 반환

def shift_decrypt(key, ctx): #쉬프트 복호화 함수
    length = len(ctx) #암호문의 길이
    msg = '' #평문
    for i in range(0, length): #암호문의 문자 개수만큼 반복
        if capital(ord(ctx[i])) == 1: #대문자라면
            msg += chr(ord('A') + ((ord(ctx[i]) - ord('A')) - key) % 26) #대문자 기준 -key만큼 문자를 shift
        else: #소문자라면
            msg += chr(ord('a') + ((ord(ctx[i]) - ord('a')) - key) % 26) #소문자 기준 -key만큼 문자를 shift
    return msg #평문 반환

def vigenere_genkey(n): #vigenere 암호의 키 생성 함수
    key = [] #키
    for i in range(0, n): #n개의 키를 생성
        newkey = r.randint(0, 10000) #키를 랜덤으로 생성
        while newkey in key: #혹시라도 키가 겹칠 가능성을 고려하여 동일한 키가 이미 존재할 경우
            newkey = r.randint(0, 10000) #다른 키 값을 생성
        key.append(newkey) #키 등록
    return key #키 반환

def vigenere_encrypt(key, msg): #vigenere 암호화 함수
    length = len(msg) #평문의 길이
    keylen = len(key) #키 길이
    key_index = 0 #키의 인덱스 정보
    ctx = '' #암호문
    for i in range(0, length): #평문의 문자 개수만큼 반복
        if key_index == keylen: #만약 키를 모두 사용했다면
            key_index = 0 #다시 처음부터 사용
        if capital(ord(msg[i])) == 1: #대문자라면
            ctx += chr(ord('A') + ((ord(msg[i]) - ord('A')) + key[key_index]) % 26) #대문자 기준, 블럭안의 문자와 대응하는 key만큼 shift
            key_index += 1 #다음 키 사용
        else: #소문자라면
            ctx += chr(ord('a') + ((ord(msg[i]) - ord('a')) + key[key_index]) % 26) #소문자 기준, 블럭안의 문자와 대응하는 key만큼 shift
            key_index += 1 #다음 키 사용
    return ctx #암호문 반환
    
def vigenere_decrypt(key, ctx): #vigenere 복호화 함수
    length = len(ctx) #암호문의 길이
    keylen = len(key) #키 길이
    key_index = 0 #키의 인덱스 정보
    msg = '' #평문
    for i in range(0, length): #평문의 문자 개수만큼 반복
        if key_index == keylen: #만약 키를 모두 사용했다면
            key_index = 0 #다시 처음부터 사용
        if capital(ord(ctx[i])) == 1: #대문자라면
            msg += chr(ord('A') + ((ord(ctx[i]) - ord('A')) - key[key_index]) % 26) #대문자 기준, 블럭안의 문자와 대응하는 -key만큼 shift
            key_index += 1 #다음 키 사용
        else: #소문자라면
            msg += chr(ord('a') + ((ord(ctx[i]) - ord('a')) - key[key_index]) % 26) #소문자 기준, 블럭안의 문자와 대응하는 -key만큼 shift
            key_index += 1 #다음 키 사용
    return msg #평문 반환

def lfsr_genkey(n): #lfsr 암호 키 생성 함수
    cdata = [] #정수
    xdata = [] #초기값
    key = [] #c_i와 x_i가 들어갈 키
    for i in range(0, n): #n만큼 반복
        #c값과 x값을 받음
        newcdata = r.randint(0, 25)
        newxdata = r.randint(0, 25) 
        #받은 c값과 x값이 c_i와 x_i과 같은 확률을 감안, 동일한 값이 이미 등록되어 있을 경우 값을 다시 받음
        while newcdata in cdata:
            newcdata = r.randint(0, 25)
        cdata.append(newcdata)
        while newxdata in xdata:
            newxdata = r.randint(0, 25)
        xdata.append(newxdata)
    key.append(cdata) #c등록
    key.append(xdata) #x등록
    return key #키 반환
    
def lfsr_encrypt(real_key, msg): #lfsr 암호화 함수
    key = c.deepcopy(real_key) #키는 사용자끼리 공유하므로 이번 실습에선 깊은 복사를 통해 사용
    length = len(msg) #평문의 길이
    keylen = len(key[1]) #x_i의 길이
    clen = len(key[0]) #c_i의 길이
    c_index = 0 #c의 인덱스
    newx = 0 #암호화에 사용되기 위해 만들어진 x값
    ctx = '' #암호문
    for i in range(0, length): #평문의 길이만큼 반복
        keylen = len(key[1]) #x(key)의 길이를 다시 저장
        for j in range(0, keylen): #x(key)의 길이만큼 반복
            if c_index == clen: #만약 c값을 모두 이용했다면
                c_index = 0 #처음부터 다시 사용
            newx += key[0][c_index] * key[1][j] #암호화에 사용되기 위해 제작된 x값
            c_index += 1 #다음 c값 사용
        newx = newx % 26 #x값을 mod 26연산으로 다음 x값 계산을 준비
        key[1].append(newx) #x값 등록
        if capital(ord(msg[i])) == 1: #대문자라면
            ctx += chr(ord('A') + ((ord(msg[i]) - ord('A')) + newx) % 26) #x를 더한 후 mod연산
        else: #소문자라면
            ctx += chr(ord('a') + ((ord(msg[i]) - ord('a')) + newx) % 26) #x를 더한 후 mod연산
    return ctx #암호문 반환

def lfsr_decrypt(real_key, ctx): #lfsr 복호화 함수
    key = c.deepcopy(real_key) #키는 사용자끼리 공유하므로 이번 실습에선 깊은 복사를 통해 사용
    length = len(ctx) #암호문의 길이
    keylen = len(key[1]) #x_i의 길이
    clen = len(key[0]) #c_i의 길이
    c_index = 0 #c의 인덱스
    newx = 0 #복호화에 사용되기 위해 만들어진 x값
    msg = '' #평문
    for i in range(0, length): #암호문의 길이만큼 반복
        keylen = len(key[1]) #x(key)의 길이를 다시 저장
        for j in range(0, keylen): #x(key)의 길이만큼 반복
            if c_index == clen: #만약 c값을 모두 이용했다면
                c_index = 0 #c처음부터 다시 사용
            newx += key[0][c_index] * key[1][j] #복호화에 사용되기 위해 제작된 x값
            c_index += 1 #다음 c값 사용
        newx = newx % 26 #x값을 mod 26연산으로 다음 x값 계산을 준비
        key[1].append(newx) #x값 등록
        if capital(ord(ctx[i])) == 1: #대문자라면
            msg += chr(ord('A') + ((ord(ctx[i]) - ord('A')) - newx) % 26) #-x를 더한 후 mod연산
        else: #소문자라
            msg += chr(ord('a') + ((ord(ctx[i]) - ord('a')) - newx) % 26) #-x를 더한 후 mod연산
    return msg #평문 반환
728x90

'Sejong University > Symmetric-key cryptography' 카테고리의 다른 글

CBC mode  (0) 2022.04.23
Simple DES  (0) 2022.04.23
Histogram for Character Frequency  (0) 2022.04.23

댓글