파이썬 AES로 암호화하고 푸는 방법

데이터 통신시 데이터 유출은 심각한 문제가 될 수 있습니다.

그래서 업무에서는 주요 데이터를 암호화해서 전송하는데요.

오늘은 이때 암호화를 하고 푸는 방법을 알아보겠습니다.

AES 관련 패키지 설치

파이썬에서는 암호화 패키지를 제공하고 있습니다.

pycryptodome입니다.

 

Welcome to PyCryptodome’s documentation — PyCryptodome 3.14.1 documentation

 

pycryptodome.readthedocs.io

예전부터 사용되던 PyCrypto와 호환성을 갖게 만든것이 pycryptodome이구요.

아예 새로운 라이브러리는 pycryptodomex입니다.

pip3 install pycryptodome

원하시는 버전을 설치하시면 됩니다.

파이썬 AES암호화 샘플코드

자습서에 있는 샘플코드를 활용하여 간단한 예제를 만들 수 있는데요.

from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes

data = b'secret data'

key = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_EAX)
ciphertext, tag = cipher.encrypt_and_digest(data)

file_out = open("encrypted.bin", "wb")
[ file_out.write(x) for x in (cipher.nonce, tag, ciphertext) ]
file_out.close()

암호화를 위해서는 키가 필요하구요. 여기서는 랜덤으로 키를 만들었습니다.

AES는 <Advanced Encryption Standard>의 약자로 '고급 암호화 표준'라는 의미이다. AES는 미국 표준 기술 연구소에 의해서 연방 정보 처리 표준으로 지정된 암호화 방식이며 NSA에 의해 1급 비밀에 사용할 수 있도록 승인된 암호화 알고리즘 중 유일하게 공개된 알고리즘이다. 대칭키를 쓰는 블럭 암호이다. 높은 안전성과 속도로 인해 인기를 얻어 전 세계적으로 많이 이용되고 있다. 이러한 이점으로 인해서 랜섬웨어에 많이 이용되고 있기도 하다.

현재 AES는 DES(데이터 암호화 표준)의 뒤를 이을 AES(고급 암호화 표준)라는 이름을 걸고 미국 표준 기술 연구소가 주최한 공모전에서 채택된 Rijndael(레인달) 알고리즘을 가리킨다. 엄밀하게는 Rijndael 알고리즘의 여러 가능성 중, 암호화 블럭의 크기가 128비트이며 암호화 키의 길이가 128, 192, 256비트인 세 가지 종류가 AES 표준으로 지정되었다. 각각 AES-128, AES-192, AES-256으로 불린다.

그리고 기본적으로  AES는 128비트키(16바이트)키를 사용하는데요.

이 때문에 16바이트가 안되는 키의 경우 Padding이라는 의미없는 값으로 채우는 과정이 필요합니다.

예전에는 직접 Padding을 구현하여 만들기도 했는데요.

pad = lambda s: s + (BS - len(s.encode()) % BS) * chr(BS - len(s.encode()) % BS)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]

최근에는 라이브러리로 지원하기 때문에 라이브러리를 불러오면 됩니다.

그리고 또하나의 과정이 있는데요. Email등의 경우에는 base64로 인코딩을 합니다.

통신과정에서 Base64는 일반적으로 바이너리 데이터의 손실을 막기 위해 사용됩니다.

 Binary Data(이미지나 오디오)를 전송할 필요가 있을 때, ASCII로 Encoding 하여 전송하게 되면

7bit Encoding인 ASCII는 나머지 1비트를 처리하는 방식이 시스템으로 달라서 여러 가지 문제가 발생할 수 있습니다.
 
그래서 일반적으로 통신에는 Base64로 한번 더 인코딩하여 통신하게 됩니다.

BASE64의 변환표는 아래와 같습니다.

간단히 암호화하는 방법을 알아보면

아래처럼 Crypto.Util.Padding을 통해서 pad랑 unpad를 불러오고,

key를 16비트로 맞추지 못햇기 때문에, 패딩으로 키의 길이를 맞춰줍니다.

인코딩은 AES_ECB방식으로 인코딩하였습니다.

from Crypto.Util.Padding import pad, unpad
from Crypto.Cipher import AES
import base64

#padding 설정
BS = 16
#pad = lambda s: s + (BS - len(s.encode()) % BS) * chr(BS - len(s.encode()) % BS)
#unpad = lambda s: s[:-ord(s[len(s) - 1:])]

#변수 설정

key = 'testkey'
ori = 'test@doru.com'
print('ori',ori)

#암호화
cipher = AES.new(pad(key.encode(), BS), AES.MODE_ECB)
msg = cipher.encrypt(pad(ori.encode(), BS))
print('msg',msg)
m2 = base64.b64encode(msg)
print('base64',m2)

실제로 실행하여 암호화와 복화를 진행하면 아래와 같습니다.

정상적으로 암호와와 복호화가 진행됨을 알 수 있습니다.

그럼 잘 사용하시기 바랍니다.

728x90

해당 블로그에서 발행되는 콘텐츠 중 일부 글에는 제휴 및 홍보 관련 링크가 포함될 수 있으며, 파트너스 활동의 일환으로 일정액의 수수료를 받을 수 있습니다.