본문 바로가기
Python

Python을 이용한 3DES 암호화 구현하기.

by 웹하는빡통 2020. 1. 2.

2020년 경자년 (庚子年)의 새해가 밝았습니다. 2020년 우리 모두 좋은 일만 가득하길 소망합니다~~!!!!!!!!!!

"경자년": '육십간지 중 37번째로 경(庚)이 백색, 자(子)가 쥐를 의미하는 '하얀 쥐의 해'

 

이번 시간에는 Python을 이용한 3DES 암호화를 구현해보도록 할께요~

실습 환경 설정 

1. Pycryptodome 설치

Pycryptodome: SHA256과 같은 해시 함수와 AES,DES,RSA등 다양한 암호 알고리즘을 제공하는 패키지임)

참고로 Python 2버전은 Pycypto입니다.

2. Python 3.7버전. 

 

자 그럼 Pycryptodome을 이용하여 3DES를 활용한 단순 메시지 암호화 도구를 만들어 보겠습니다.

 

1. Crypto.Cipher import 3DES 와 Crypto.Hash SHA256

1. 3DES 라이브러리를 사용을 위해 Pycryptodome의 필요한 모듈을 import를 해준다.

3DES 모듈은 Cyprto.Cipher이다.

2. 그 아래 Crypto.Hash import SHA256 as SHA는 3DES의 암호키와 초기벡터(IV)를 만들기 위해서다.

초기화 벡터(initialization vector, IV): 첫 블록을 암호화할 때 사용되는 값을 의미한다.

여기서 IV의 생성에 앞서 IV는 반드시 송수신 양자 모두가 알고 있어야 하고 제3자로부터의 예측이 불가능해야 한다.

 

2. class [변수이름](): 선언 

1. 일단 3DES를 위해 myDES라는 클래스를 정의하자 이름정의는 여러분들의 취향대로 해도 상관없다.

2 이 클래스에는 3DES로 암호화를 수행하는 enc()3DES로 복호화를 수행하는 dec() 메소드가 정의되어 있다.

 

3. __init__() 클래스 생성자.

자 다음은 __init__()클래스 생성자를 만들어주자 그리고

클래스 생성자의 인자 keytext3DES 암호키 생성을 위한 문자열이며, ivtextIV를 위한 문자열이다.

클래스 생성자에서 3DES 객체 생성 시 사용할 키와 IV를 구한다. 

 

※ 여기서 잠깐 

만약 keytext='abcdefghijklmnop'와 같이 keytext의 길이가 16바이트가 되어 3DES가 지원하는 키 크기와 같다면 keytext를 바로 암호키로 활용할 수 있겠지만 16자 이상이 되는 키는 외우기 힘들뿐더러 관리하기도 힘들다.

그래서 편하게 그냥 3DES가 지원하는 길이로 만들어서 3DES의 키로 활용하면 보다 더 편리할 거다. SHA256 해시는 이런 작업을 수행할 수 있는 아주 훌륭한 도구이다. 

 

4. SHA.new()를 이용한 SHA256객체 만들기.

 이제 클래스도 만들고 모듈도 썼으니 객체를 만들어 보자. 

 

1. SHA.new()를 이용하여 SHA객체를 만들고 hash라는 변수에 할당한다.

2. 그 다음 hash.update()를 이용해 SHA해시를 갱신하고 여기서 해시 갱신을 위해 사용된 인자는 keytext이며 입력된 인자 값에 따라 갱신되는 해시 값이 정해진다.

 

※ 또 여기서 잠깐

여기서 hash.update는 유니코드 문자열을 인자로 받지 않는다 그런데 파이썬 3버전에선 모든 문자열은 유니코드이다. 

 

이렇게 인자로 유니코드로 된 문자열을 입력 받으면 위와 같이 오류가 난다.

 

why?? 

파이썬 3버전에서는 UTF-8로 인코딩된 문자열은 문자열이 아니라 이진데이터가 연속적으로 있는 바이트 스트림으로 취급하기 때문이다.   

 

그리고 블록 암호에서 CBC 모드로 암호화하기 위해서는 IV(초기벡터)가 필요하다. 암호학을 공부하셨거나 관심이 있는 사람들은 알 것 이다.

CBC 모드: Cipher Block Chaining mode(암호 블록 연쇄 모드)

 

3DES는 64비트 암호화 블록 크기를 가지는데 그래서 IV도 반드시 64비트여야 한다.

여기도 암호키 생성과 마찬가지로 IV 생성을 위해 SHA 해시를 활용하기 위해 hash.update(ivtext.encode('utf-8'))로 IV를 위한 해시를 갱신한 다음

hash.digest()로 해시 값을 얻은 후 변수 iv에 할당한다. iv의 처음 8바이트를 초기벡터 값으로 할당한다. 

 

5.  def enc()로 암호화.

enc()는 인자로 입력된 plaintext에 담긴 문자열을 3DES로 암호화 해준다.

암호화를 위해 먼저 DES3.new()로 3DES 객체를 생성

DES3.new()의 인자는 순서대로 '암호키', '운영모드', '초기벡터' 임.

마지막으로 . des3.encrypt()로 암호화를 수행 후 그 결과를 리퉌 해준다. 

 

※ 여기서 주의 할 점이 있다.

초기벡터 같은 경우는 운영모드에 따라서 필요 유/무가 있다. 예를 들어 ECB,CTR 모드 같은 경우는 초기 벡터가 필요없다. 따라서 운영모드에 따라 DES3.new()의 3번째 인자가 있을 수 있고 없을 수 있다는 얘기이다. 

 

6. def dec()로 복호화. 

자 그러면 암호화를 했으면 복호화도 해야지 ^^ 

코드는 아까 암호화 코드랑 똑같으니 설명은 하지 않겠다. 

 

7. 프로그램 수행을 위한 def main()

마지막으로 프로그램을 수행하기 위한 main 함수를 선언하자. 

keytext로 'sungchan', 초기벡터 생성을 위한 ivtext로 '1234'를 이용하자 

여기서 우리가 기억해야 하는 암호키sungchan이 되며

코드 내부에서 실제 운영되는 암호키sungchan의 SHA256 해시값 중 처음 24바이트가 된다. ivtext도 똑같다.

아까 위에서 말했듯이 암호화 블록 크기와 IV랑 같아야 한다고 했었다. 

 

그리고 암호화하려는 메시지는 사진과 같이 I KILL YOU이다. 이제 프로그램을 실행해보자. 

 

결과.

실행 결과 정상적으로 결과가 출력이 되었다.

여기서 'b'로 표시된 것은 문자열이 아닌 바이트 객체라는 것을 나타내는 것이다. 

다시 한번 말하지만 파이썬 3버전에서 나온 이 결과 값은 유니코드가 아니고

바이트 스트림인 이진데이터이다. 꼭 기억해두자. 

 

전체 소스코드. 

댓글