hashlib — 보안 해시와 메시지 다이제스트

hashlib — 보안 해시와 메시지 다이제스트

hashlib 모듈은 많은 서로 다른 보안 해시·메시지 다이제스트 알고리즘에 대한 공통 인터페이스를 제공해요. 여기에는 FIPS 보안 해시 알고리즘 SHA1, SHA224, SHA256, SHA384, SHA512(미국 표준 'Secure Hash Standard'에 정의)뿐 아니라 RSA의 MD5 알고리즘('Internet RFC 1321'에 정의된)도 포함됩니다. "보안 해시"와 "메시지 다이제스트"라는 용어는 서로 바꿔 쓸 수 있어요. 여러 요약 알고리즘도 이 모듈에서 제공합니다.

출처: Python 표준 라이브러리

해시 알고리즘

hashlib에는 구축 가능한 해시 알고리즘들이 있어요. 각 알고리즘은 고유한 이름을 가지고 있고, hashlib.new()에 문자열 이름으로 전달할 수 있어요. 다음 표는 자주 쓰는 알고리즘을 보여 줍니다:

  • md5 — 128비트 다이제스트
  • sha1 — 160비트 다이제스트
  • sha224, sha256, sha384, sha512, sha512_224, sha512_256 — FIPS 보안 해시
  • sha3_224, sha3_256, sha3_384, sha3_512 — SHA-3 계열
  • blake2b, blake2s — BLAKE2 계열
  • shake_128, shake_256 — 가변 길이 다이제스트(XOF)

hash 객체 만들기

hashlib.new(name, [data, ]*, usedforsecurity=True) — 이 생성 함수는 이름이 가리키는 알고리즘의 새 해시 객체를 만들어요. data는 선택적으로 초기 청크로 제공됩니다.

또는 직접 생성자를 쓸 수도 있어요. 각 알고리즘마다 단일 업데이트 호출로 전체 데이터를 해시하는 최적화된 경로가 제공됩니다. 예를 들어 hashlib.sha256(b'data')처럼요.

해시 객체 사용하기

생성된 해시 객체는 한 번에 조금씩 데이터를 공급해 해시를 누적할 수 있는 API를 제공해요 (GIL이 해제되므로 큰 데이터에 유리해요):

>>> import hashlib
>>> m = hashlib.sha256()
>>> m.update(b"Nobody inspects")
>>> m.update(b" the spammish repetition")
>>> m.digest()
b'\x03\x1e\xdd}Ae\x15\x93\xc5\xfe\\\x00o\xa5u+7\xfd\xdf\xf7\xbcN\x84:\xa6\xaf\x0c\x95\x0fK\x94\x06'
>>> m.hexdigest()
'031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406'

해시 객체 메서드·속성

  • hash.update(data)data(bytes류)로 해시 객체를 갱신해요. 반복 호출은 모든 인자를 이어 붙인 단일 호출과 동일합니다.
  • hash.digest() — 지금까지 update()에 전달된 bytes의 다이제스트를 반환해요. 이 bytes 객체는 digest_size와 같은 길이입니다.
  • hash.hexdigest() — 다이제스트를 16진수 숫자만 담은 문자열로 반환해요.
  • hash.copy() — 해시 객체의 복사본("클론")을 반환해요. 공통 초기 부분 문자열을 공유하는 문자열들의 다이제스트를 효율적으로 계산할 때 쓰입니다.
  • hash.digest_size — 결과 해시의 크기(바이트).
  • hash.block_size — 내부 블록 크기(바이트).
  • hash.name — 이 해시의 정식 이름(항상 소문자), 예: 'sha256'.
>>> m = hashlib.sha256()
>>> m.update(b"Nobody inspects")
>>> m.update(b" the spammish repetition")
>>> m.digest_size
32
>>> m.block_size
64
>>> m.name
'sha256'

usedforsecurity 옵션

hashlib.new(), hashlib.md5() 등 모든 생성자에는 usedforsecurity 키워드 인자가 있어요. 기본값은 True이고, 시스템이 보안 목적이 아닌 일부 해시 사용을 거부하도록 구성된 FIPS 호환 환경에서 이 인자를 False로 주면 해시를 계산할 수 있게 합니다. 예:

>>> md5 = hashlib.new('md5', usedforsecurity=False)

키 파생 함수

해시 함수는 비밀번호나 기타 신뢰할 수 없는 입력으로부터 키를 파생하는 데에도 사용됩니다:

  • hashlib.pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None) — PBKDF2 키 파생 함수예요. hash_name은 HMAC에 사용할 해시 알고리즘 이름입니다.
>>> import hashlib, binascii
>>> dk = hashlib.pbkdf2_hmac('sha256', b'password', b'salt', 100000)
>>> binascii.hexlify(dk)
b'0394a2ede332c9a13eb82e9b24631604c31df978b4e2f0fbd2c549944f9d79a5'
  • hashlib.scrypt(password, *, salt, n, r, p, maxmem=0, dklen=64) — 메모리 하드한 키 파생 함수인 scrypt를 제공해요. 브루트포스에 강합니다.
>>> import hashlib, binascii
>>> dk = hashlib.scrypt(b'password', salt=b'salt', n=2**14, r=8, p=1, dklen=64)
>>> binascii.hexlify(dk)
b'...'
  • hashlib.file_digest(fileobj, digest, *, _bufsize=...) — 파일 객체의 다이제스트를 계산해요. digest는 해시 생성자이거나 알고리즘 이름입니다.

BLAKE2

hashlib는 최신 암호 해시 함수 BLAKE2b(64비트 최적화)와 BLAKE2s(8~32비트 최적화)도 제공해요. BLAKE2는 무작위 해시 및 키 해시를 지원하며, 빠른 속도가 특징입니다.

>>> from hashlib import blake2b
>>> h = blake2b()
>>> h.update(b'Hello world')
>>> h.hexdigest()
'6ff843ba685facaa2d6c4e7e2e2d0c77d3f5b8e9fc5f1f4f9f...'

BLAKE2b와 BLAKE2s의 생성자는 digest_size, key, salt, person 같은 추가 인자를 받습니다.

다이제스트 예제

파일 전체를 해시하는 방법:

import hashlib

def hash_file(filename, algorithm='sha256'):
    h = hashlib.new(algorithm)
    with open(filename, 'rb') as f:
        for chunk in iter(lambda: f.read(4096), b''):
            h.update(chunk)
    return h.hexdigest()

나인 간단한 문자열 해시:

>>> import hashlib
>>> hashlib.sha256(b'Hello world').hexdigest()
'64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c'

더 알아보기

  • Python 표준 라이브러리의 hmac 모듈 — 키 기반 해시
  • Python 표준 라이브러리의 secrets 모듈 — 안전한 난수 생성
  • Python 공식 문서: hashlib