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

Simple DES

by reindeer002 2022. 4. 23.
728x90
import random as r #키값 생성을 위한 랜덤모듈

def sdes_genkey(): #키 생성 함수
    key = [] #키
    for i in range(0, 9): #키의 개수가 9개
        key.append(r.randint(0, 1)) #랜덤하게 키를 받음
    return key #키 반환

def sdes_encrypt(key, pblock): #암호화 함수
    Rblock = pblock[6:] #오른쪽 블록
    Lblock = pblock[0:6] #왼쪽 블록
    for i in range(0, 3): #simple DES이므로 3번의 사이클로 구성
        exRblock = expander(Rblock) #블록 8비트로 확장
        usekey = keygenerator(key, i) #8비트 키 생성
        result = XOR(exRblock, key) #키와 확장한 블록을 XOR함
        resultLeft = result[0:4] #결과의 왼쪽 블록
        resultRight = result[4:] #결과의 오른쪽 블록
        funcResult = SBox(resultLeft, resultRight) #왼쪽, 오른쪽 블록의 비트에 해당하는 SBOX값
        if i == 2: #만약 마지막 사이클이라면
            Lblock, Rblock = XOR(funcResult, Lblock), Rblock #교환하지 않음
        else: #마지막 사이클이 아니라면
            Rblock, Lblock = XOR(funcResult, Lblock), Rblock #교환
    return Lblock+Rblock #완성된 암호문 반환

def sdes_decrypt(key, cblock): #복호화 함수
    Rblock = cblock[6:] #오른쪽 블록
    Lblock = cblock[0:6] #왼쪽 블록
    for i in range(0, 3): #simple DES이므로 3번의 사이클로 구성
        exRblock = expander(Rblock) #블록 8비트로 확장
        usekey = keygenerator(key, i) #8비트 키 생성
        result = XOR(exRblock, key) #키와 확장한 블록을 XOR함
        resultLeft = result[0:4] #결과의 왼쪽 블록
        resultRight = result[4:] #결과의 오른쪽 블록
        funcResult = SBox(resultLeft, resultRight) #왼쪽, 오른쪽 블록의 비트에 해당하는 SBOX값
        if i == 2: #만약 마지막 사이클이라면
            Lblock, Rblock = XOR(funcResult, Lblock), Rblock #교환하지 않음
        else: #마지막 사이클이 아니라면
            Rblock, Lblock = XOR(funcResult, Lblock), Rblock #교환
    return Lblock+Rblock #완성된 암호문 반환

def expander(block): #확장 함수
    result = [] #확장된 결과
    result.append(block[0])
    result.append(block[1])
    result.append(block[3])
    result.append(block[2])
    result.append(block[3])
    result.append(block[2])
    result.append(block[4])
    result.append(block[5])
    #123456의 블록을 12434356으로 확장함
    return result #결과 반환

def keygenerator(key, n): #키 생성
    usekey = [] #사용할 8비트 키
    for i in range(0, 8): #8번 반복
        if n == len(key): #만약 마지막 키에 도달했다면
            n = 0 #처음 키로 돌아가 다시 생성
        usekey.append(key[n]) #사용할 키 등록
        n += 1 #다음 키를 들고 오기 위한 증가
    return usekey #사용할 8비트 키 반환

def XOR(block1, block2): #XOR연산(단, 이는 ^연산자를 사용하지 않음)
    result = [] #연산 결과
    for i in range(0, len(block1)): #XOR할 대상의 크기 만큼 반복
        if block1[i] == block2[i]: #만약 두 비트가 같다면
            result.append(0) #0 저장
        else: #만약 두 비트가 다르다면
            result.append(1) #1저장
    return result #연산 결과 반

def SBox(left, right): #SBOX값으로 변환하는 함수
    leftpos = 0 #왼쪽 블록의 오른쪽 3비트의 10진
    rightpos = 0 #오른쪽 블록의 오른쪽 3비트의 10진
    value = 1
    sbox1 = [[[1,0,1], [0,1,0], [0,0,1], [1,1,0], [0,1,1], [1,0,0], [1,1,1], [0,0,0]],
             [[0,0,1], [1,0,0], [1,1,0], [0,1,0], [0,0,0], [1,1,1], [1,0,1], [0,1,1]]] #sbox1의 형태
    sbox2 = [[[1,0,0], [0,0,0], [1,1,0], [1,0,1], [1,1,1], [0,0,1], [0,1,1], [0,1,0]],
             [[1,0,1], [0,1,1], [0,0,0], [1,1,1], [1,1,0], [0,1,0], [0,0,1], [1,0,0]]] #sbox2의 형태
    for i in reversed(range(1, 4)): #3, 2, 1순서로 반복
        if left[i] == 1: #만약 비트가 1이라면
            leftpos += value #value값 더하기
        if right[i] == 1: #만약 비트가 1이라면
            rightpos += value #value값 더하기
        value *= 2 #value값에 2 곱하기(2진수 표현을 하기 위함)
    return sbox1[left[0]][leftpos]+sbox2[right[0]][rightpos] #반환된 SBOX값 반환
728x90

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

CBC mode  (0) 2022.04.23
Classic Cipher  (0) 2022.04.23
Histogram for Character Frequency  (0) 2022.04.23

댓글