1. from Crypto.Cipher import*  
  2. from Crypto.Hash import SHA256 as SHA  
  3. import os  
  4.   
  5. KSIZE = 1024  
  6.   
  7. class myDES():  
  8.     def __init__(self, keytext, ivtext):  
  9.         hash = SHA.new()  
  10.         hash.update(keytext.encode('utf-8'))  
  11.         key = hash.digest()  
  12.         self.key = key[:24]  
  13.   
  14.         hash.update(ivtext.encode('utf-8'))  
  15.         iv = hash.digest()  
  16.         self.iv = iv[:8]  
  17.   
  18.     def makeEncInfo(self, filename):  
  19.         fillersize = 0  
  20.         filesize = os.path.getsize(filename)  
  21.         if filesize % 8 != 0:  
  22.             fillersize = 8 - filesize % 8  
  23.         filler = '0'*fillersize  
  24.         header = '%d'%(fillersize)  
  25.         gap = 8 - len(header)  
  26.         header += '#'*gap  
  27.   
  28.         return header, filler  
  29.   
  30.     def enc(self, filename):  
  31.         encfilename = filename + '.enc'  
  32.         header, filler = self.makeEncInfo(filename)  
  33.         des3 = DES3.new(self.key, DES3.MODE_CBC, self.iv)  
  34.   
  35.         f = open(filename, 'rb')  
  36.         p = open(encfilename, 'wb+')  
  37.   
  38.         enc = header.encode('utf-8')  
  39.         content = f.read(KSIZE)  
  40.         content = enc + content  
  41.   
  42.         while content:  
  43.             if len(content) < KSIZE:  
  44.                 content += filler.encode('utf-8')  
  45.             enc = des3.encrypt(content)  
  46.             p.write(enc)  
  47.             content = f.read(KSIZE)  
  48.         f.close()  
  49.         p.close()  
  50.   
  51.     def dec(self, encfilename):  
  52.         filename = encfilename + '.dec'  
  53.         des3 = DES3.new(self.key, DES3.MODE_CBC, self. )  
  54.   
  55.         f = open(filename, 'wb+')  
  56.         p = open(filename, 'rb')  
  57.   
  58.         content = p.read(8)  
  59.         dec = des3.decrypt(content)  
  60.         header = dec.decode()  
  61.         fillersize = int(header.split('#')[0])  
  62.   
  63.         content = p.read(KSIZE)  
  64.         while content:  
  65.             dec = des3.decrpyt(content)  
  66.             if len(dec) < KSIZE:  
  67.                 if fillersize != 0:  
  68.                     dec = dec[:-fillersize]  
  69.             f.write(dec)  
  70.             content = p.reae(KSIZE)  
  71.         f.close()  
  72.         p.close()  
  73.   
  74. if __name__ == "__main__":  
  75.     keytext = 'iloveyou'  
  76.     ivtext = '1234'  
  77.     filename = 'plain.txt'  
  78.     encfilename = filename + '.enc'  
  79.   
  80.     myCipher = myDES(keytext, ivtext)  
  81.     myCipher.enc(filename)  
  82.     myCipher.dec(encfilename)  


[코드 1] 3DES 파일 암 복호화 코드 - 3desforfile.py



설명


모든 크기의 파일에 대해 3DES로 암호화, 복호화 가능한 코드이다.


단문 메세지 암호화 코드와의 차이점은 지정된 파일에 있는 모든 내용을 읽고 암호화 한후 새로운 파일에 기록하는 부분이다. 단문 메세지 암호화 코드와 대비되는 코드를 살펴보자.



  1.     def makeEncInfo(self, filename):  


지정된 파일 크기를 구하고 파일 크기가 8byte 배수가 아닐 경우 8바이트 배수로 만들기 위해 추가할 '0' 문자열을 구성한다. 그리고 추가할 문자 '0'의 개수에 대한 정보를 헤더로 만든다. 


헤더, 추가할 '0' 문자열을 리턴한다.


[ 암호화 로직 ]


  1.         encfilename = filename + '.enc'  
  2.         header, filler = self.makeEncInfo(filename)  


지정된 파일 내용을 1KB씩 읽어서 3DES로 암호화 한 후 새로운 파일에 저장한다.

암호화 된 내용을 저장할 파일 이름은 원래 파일 이름에 .enc 확장자를 추가하여 만든다.

self.makeEncInfo(filename)을 호출하여 헤더와 '0' 문자열을 얻고 각각 변수 header와 filler에 할당한다.



  1.         enc = header.encode('utf-8')  
  2.         content = f.read(KSIZE)  
  3.         content = enc + content  


파일에서 1KB 씩 읽어서 content에 할당한다. header를 content 앞에 추가한다.

만약 파일 내용이 1KB 미만이면 file.read( )는 남아 있는 크기만큼 모두 읽는다.


  1.         while content:  
  2.             if len(content) < KSIZE:  
  3.                 content += filler.encode('utf-8')  
  4.             enc = des3.encrypt(content)  
  5.             p.write(enc)  
  6.             content = f.read(KSIZE)  


content에 내용이 없을 때 까지 while 구문을 수행한다.

만약 content의 크기가 KSIZE, 즉 1KB보다 작다면 파일의 끝까지 읽었다는 의미이다.

따라서 이부분에서 '0' 문자열을 content에 추가한다.


content를 3DES로 암호화하고 파일에 저장한 후, 파일에 다시 1KB만큼 읽어  content에 할당한다.


[ 복호화 로직 ]


dec(self, encfilename)은 encfilename 으로 지정된 암호화된 파일 내용을 

1KB 씩 읽어서 3DES로 복호화 한 후 새로운 파일에 저장한다.


  1.         content = p.read(8)  
  2.         dec = des3.decrypt(content)  
  3.         header = dec.decode()  
  4.         fillersize = int(header.split('#')[0])  


암호화 파일에서 최초 8byte를 읽어 3DES로 복호화 한다. 최초 8byte는 헤더이므로 '#'을 구분자로 헤더를 분리한 후 첫번째 멤버를 정수로 변환하면 이 파일의 끝부분에 추가된 문자 '0'의 개수를 얻을 수 있다.


  1.         content = p.read(KSIZE)  
  2.         while content:  
  3.             dec = des3.decrpyt(content)  
  4.             if len(dec) < KSIZE:  
  5.                 if fillersize != 0:  
  6.                     dec = dec[:-fillersize]  
  7.             f.write(dec)  
  8.             content = p.reae(KSIZE) 


암호화 파일에서 1KB를 먼저 읽고 content에 할당한다. content에 내용이 없을때 까지 반복 수행한다.


content를 3DES로 복호화 하고 파일에 저장한다.만약 복호화 한 결과가 1KB 보다 작으면 복호화 파일의 마지막 부분이므로 암호화 때 추가한 '0' 문자열을 제거하고 파일에 저장한다.


[ AES로 구현하기 ]


코드는 크게 틀리지 않다. 틀린 부분을 굵은 글씨로 표시하였다.


  1. #-*- coding: utf-8 -*-  
  2. from Crypto.Cipher import AES  
  3. from Crypto.Hash import SHA256 as SHA  
  4. import os  
  5. KSIZE = 1024  
  6.   
  7. class myAES():  
  8.     def __init__(self, keytext, ivtext):  
  9.         hash = SHA.new()  
  10.         hash.update(keytext.encode('utf-8'))  
  11.         key = hash.digest()  
  12.         self.key = key[:16]  
  13.   
  14.         hash.update(ivtext.encode('utf-8'))  
  15.         iv = hash.digest()  
  16.         self.iv = iv[:16]  
  17.   
  18.     def makeEncInfo(slef, filename):  
  19.         fillersize = 0  
  20.         filesize = os.path.getsize(filename)  
  21.         if filesize % 16 != 0:  
  22.             fillersize = 16 - filesize % 16  
  23.   
  24.         filler = '0'*fillersize  
  25.         header = '%d' %(fillersize)  
  26.         gap = 16 - len(header)  
  27.         header += '#'*gap  
  28.   
  29.         return header, filler  
  30.   
  31.     def enc(self, filename):  
  32.         encfilename = filename + '.enc'  
  33.         header, filler = self.makfeEncInfo(filename)  
  34.         aes = AES.new(self.key, AES.MODE_CBC, self.iv)  
  35.   
  36.         f = open(filename, 'rb')  
  37.         p = open(encfilename, 'wb+')  
  38.   
  39.         enc = header.encode('utf-8')  
  40.         content = f.read  
  41.         content = enc + content  
  42.   
  43.         while content:  
  44.             if len(content) < KSIZE:  
  45.                 content += filler.encode('utf-8')  
  46.   
  47.             enc = aes.encrypt(content)  
  48.             p = write(enc)  
  49.             content = f.read(KSIZE)  
  50.   
  51.         f.close()  
  52.         p.close()  
  53.   
  54.     def dec(self, encfilename):  
  55.         filename = encfilename + '.dec'  
  56.         aes = AES.new(self.key, AES.MODE_CBC, self.iv)  
  57.   
  58.         f.open(filename, 'wb+')  
  59.         p = open(encfilename, 'rb')  
  60.   
  61.         content = p.read(16)  
  62.         dec = aes.decrypt(content)  
  63.         header = dec.decode()  
  64.         fillersize = int(header.split('#')[0])  
  65.   
  66.         content = p.read(KSIZE)  
  67.         while content:  
  68.             dec = aes.decrypt(content)  
  69.             if fillersize != 0:  
  70.                 dec = dec[:-fillersize]  
  71.             f.write(dec)  
  72.             content = p.read(KSIZE)  
  73.   
  74.         f.close()  
  75.         p.close()  


[코드 2] AES 파일 암 복호화 코드 - aesforfile.py

'Crypto > pycrypto' 카테고리의 다른 글

RSA 공개키 암호 구현 - pycrypto  (0) 2017.02.05
3. ARC4 - pycrypto  (0) 2017.02.03
2. AES - pycrypto  (0) 2017.02.02
1. 3DES - pycrypto  (0) 2017.02.02

+ Recent posts