바로 이저의 게시글 des로 구현한 코드는 0으로 채워진 암호화를 복호화할 시 0이 없어진 상태로 복호화 되는 것이 아니라 0이 그대로 나타난다는 것이 문제점이며 이는 데이터 무결성을 보장하지 못한다는 뜻이다. 

복호화는 암호화된 암호문을 복호화시 원래의 평문과 동일함을 보장해야한다.

from Crypto.Cipher import AES
from Crypto.Hash import SHA256 as SHA

class myAES():
    def __init__(self, keytext, ivtext):
        hash = SHA.new()
        hash.update(keytext.encode('utf-8'))
        key = hash.digest()
        self.key = key[:16]

        hash.update(ivtext.encode('utf-8'))
        iv = hash.digest()
        self.iv = iv[:16]

    def makeEnabled(self, plaintext): #16바이트 배수가 아닐 경우 16바이트 배수로 만들어줌
        fillersize = 0
        textsize = len(plaintext)
        if textsize%16 !=0:
            fillersize = 16-textsize%16
        filler = '0'*fillersize
        header = '%d' %(fillersize)
        gap = 16 - len(header)
        header += '#'*gap

        return header+plaintext+filler

    def enc(self, plaintext):
        plaintext = self.makeEnabled(plaintext)
        aes = AES.new(self.key, AES.MODE_CBC, self.iv)
        encmsg = aes.encrypt(plaintext.encode())
        return encmsg
    
    def dec(self, ciphertext):
        aes = AES.new(self.key, AES.MODE_CBC, self.iv)
        decmsg = aes.decrypt(ciphertext)

        header = decmsg[:16].decode()
        fillersize = int(header.split('#')[0])  

        if fillersize != 0:
            decmsg = decmsg[16:-fillersize]
        else:
            decmsg = decmsg[16:]
        return decmsg
    
def main():
    keytext = 'samsjang'
    ivtext = '1234'
    msg = 'python3x'

    myCipher = myAES(keytext, ivtext)
    ciphered =  myCipher.enc(msg)
    deciphered = myCipher.dec(ciphered)
    print('ORIGINAL:\t%s' %msg)
    print('CIPHERED:\t%s' %ciphered)
    print('DECIPHERED:\t%s' %deciphered)

main()

DES 코드와 많이 달라 진 것은 없다. 다만 makeEnabled()함수를 잘 이해하고 넘어가야한다. 인자로 입력되는 plaintext의 크기가 16바이트 배수가 아닐 경우 문자 '0'을 plaintext 끝에 추가하여 16바이트 배수로 만들고, 이에 대한 정보를 헤더로 구성한 후 결과를 리턴한다.

헤더 크기는 16바이트로 한다. 예로 plaintext를 16바이트 배수로 만들기 위해 추가된 '0'을 개수가 12일 경우 헤더는 다음과 같이 구성된다. header = '12##############'로 총 '#'문자가 총 14개로 구성된다.  makeEnabled()로 plaintext를 "헤어+원래 정보+'0'문자열"로 변환한다.

 

그리고 split 부분 맨 뒤 [0] 인덱스가 무엇을 의미하는 지 몰라서 파이썬 idle에 실행 해보았는데 파이썬 split()함수를 사용하면 다음과 같이 자료형이 list로 반환된다. 애석하기도 이거 하다가 처음 알았음;;;;

 

split으로 '#'을 구분자로 분리하고, 분리된 값 중 첫 번째를 정수로 변환하여 변수 fillersize에 할당한다.

fillersize는 원래 정보 뒤에 추가한 문자 '0'의 개수이므로 decmsg를 16에서 -fillersize까지 슬라이싱하면 원래 정보가 추출된다.

 

출처: 화이트 해커를 위한 암호와 해킹

+ Recent posts