사용자 도구

사이트 도구


python:crypto

파이썬에서 암호화에 대하여

PyCrypto

PyCrypto(Python Cryptography Toolkit) 모듈은 2004년에 정식 버전이 배포된 오래된 암호화 모듈이다.

하지만 pip에는 2013년 10월 18일에 마지막 버전인 pycrypto 2.6.1을 배포한 이후 더이상 업데이트되지 않고 있다.

github에는 2014년 6월 20일에 마지막으로 커밋된 코드를 찾아볼 수 있다.

게다가 block_templace.c의 ALGnew 함수에서 임의 코드 실행 공격이 가능한 힙 버퍼 오버플로우 취약점이 발견되어 CVE-2013-7459에 등록되었다.

이 취약점에 대한 패치를 발표하지 않고 더이상의 업데이트도 찾아 볼 수 없다.

그래서 PyCrypto를 계승한 PyCryptodome을 사용하길 권장한다.

PyCryptodome

PyCryptodome은 PyCrypto를 fork하여 제작된 거의 동일한(drop-in replacement) 모듈이다.

즉 기존 프로그램에서 사용하던 PyCrypto를 정말 그대로 사용할 수 있도록 도와준다.

그래서 파이썬 코드에서 import 할 때도 Crypto를 import 한다.

PyCryptodomex

PyCryptodome을 사용하다보면 PyCryptodomex라는 패키지도 찾아볼 수 있다.

PyCryptodomex는 PyCryptodome의 standalone 버전이다.

PyCrypto와 PyCryptodome을 동시에 사용할 때 발생할 수 있는 문제(이름 등) 등을 회피하기 위해 만들어진 패키지다.

PyCryptodomex를 설치한 경우 Cryptodome을 import 해야 한다.

준비하기

파이썬에서 암호화 알고리즘 DES(DES3)AES, 해시함수 MD4,MD5 SHA를 이용하기 위해서는 Crypto 모듈이 필요합니다. Crypto 모듈은 기본으로 설치되어있는 모듈이 아니므로 모듈을 설치해야 합니다.

pycryptodome

pycrypto를 대체하기 위해 개선된 라이브러리로 기존 코드와 호환됩니다.

pycryptodomex

pycrypto와 독립적인 완전히 새로운 라이브러리입니다.

1. crypto 모듈을 설치

pip install pycryptodomex

2. python에서 Crypto 모듈을 import 합니다.

import Crypto

Sample Code

maro_crypto.py
import base64
import hashlib
from Cryptodome import Random
from Cryptodome.Cipher import AES
from django.conf import settings
 
 
class AESCipher:
    def __init__(self):
        self.BS = 16
        self.pad = lambda s: s + (self.BS - len(s) % self.BS) * chr(self.BS - len(s) % self.BS)
        self.unpad = lambda s: s[0:-s[-1]]
        self.key = hashlib.sha256(settings.SECRET_KEY.encode('utf-8')).digest()
 
    def encrypt(self, raw):
        raw = self.pad(raw).encode('utf-8')
        iv = Random.new().read(AES.block_size)
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        return base64.b64encode(iv + cipher.encrypt(raw))
 
    def decrypt(self, enc):
        enc = base64.b64decode(enc)
        iv = enc[:16]
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        return self.unpad(cipher.decrypt(enc[16:]))
 
    def encrypt_str(self, raw):
        return self.encrypt(raw).decode('utf-8')
 
    def decrypt_str(self, enc):
        if type(enc) == str:
            enc = str.encode(enc)
        return self.decrypt(enc).decode('utf-8')

참조

python/crypto.txt · 마지막으로 수정됨: 2025/04/15 10:05 저자 127.0.0.1