문서의 선택한 두 판 사이의 차이를 보여줍니다.
| 양쪽 이전 판이전 판다음 판 | 이전 판 | ||
| python:crypto [2024/02/02 13:37] – [준비하기] taekgu | python:crypto [2025/04/15 10:05] (현재) – 바깥 편집 127.0.0.1 | ||
|---|---|---|---|
| 줄 1: | 줄 1: | ||
| + | ====== 파이썬에서 암호화에 대하여 ====== | ||
| + | * [[python: | ||
| + | ===== 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**, | ||
| + | **Crypto** 모듈은 기본으로 설치되어있는 모듈이 아니므로 모듈을 설치해야 합니다. | ||
| + | |||
| + | === pycryptodome === | ||
| + | pycrypto를 대체하기 위해 개선된 라이브러리로 기존 코드와 호환됩니다. | ||
| + | |||
| + | === pycryptodomex === | ||
| + | pycrypto와 독립적인 완전히 새로운 라이브러리입니다. | ||
| + | |||
| + | 1. crypto 모듈을 설치 | ||
| + | <code bash> | ||
| + | pip install pycryptodomex | ||
| + | </ | ||
| + | |||
| + | 2. python에서 Crypto 모듈을 import 합니다. | ||
| + | <code python> | ||
| + | import Crypto | ||
| + | </ | ||
| + | |||
| + | ===== Sample Code ===== | ||
| + | <code python 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(' | ||
| + | |||
| + | def encrypt(self, | ||
| + | raw = self.pad(raw).encode(' | ||
| + | iv = Random.new().read(AES.block_size) | ||
| + | cipher = AES.new(self.key, | ||
| + | return base64.b64encode(iv + cipher.encrypt(raw)) | ||
| + | |||
| + | def decrypt(self, | ||
| + | enc = base64.b64decode(enc) | ||
| + | iv = enc[:16] | ||
| + | cipher = AES.new(self.key, | ||
| + | return self.unpad(cipher.decrypt(enc[16: | ||
| + | |||
| + | def encrypt_str(self, | ||
| + | return self.encrypt(raw).decode(' | ||
| + | |||
| + | def decrypt_str(self, | ||
| + | if type(enc) == str: | ||
| + | enc = str.encode(enc) | ||
| + | return self.decrypt(enc).decode(' | ||
| + | </ | ||
| + | ====== 참조 ====== | ||
| + | 참조) [[https:// | ||