사용자 인증 문서의 검증 코드다. if __name__ == "__main__": 아래가 자체 테스트다.
"""솔트를 쓴 비밀번호 저장 (Stallings 15.1절, 그림 15.1).
저장: (사용자 ID, 솔트, hash(솔트 + 비밀번호)). 확인: 저장된 솔트로 다시 해시해 비교한다.
느린 해시로 PBKDF2를 쓴다."""
import hashlib
import hmac
import os
def store(pw, salt=None, rounds=10_000):
salt = salt if salt is not None else os.urandom(16)
return salt, hashlib.pbkdf2_hmac("sha256", pw.encode(), salt, rounds)
def verify(pw, salt, h, rounds=10_000):
return hmac.compare_digest(hashlib.pbkdf2_hmac("sha256", pw.encode(), salt, rounds), h)
if __name__ == "__main__":
s1, h1 = store("hunter2")
s2, h2 = store("hunter2")
assert verify("hunter2", s1, h1) and not verify("hunter3", s1, h1)
assert h1 != h2 # 같은 비밀번호도 솔트가 다르면 저장값이 다르다
# 솔트 없이 해시하면 같은 비밀번호가 같은 값으로 드러난다
assert hashlib.sha256(b"hunter2").digest() == hashlib.sha256(b"hunter2").digest()
# 사전 공격 비용: 단어 W개, 솔트 b비트 -> 미리 만들 표는 W * 2^b개
W, b = 10 ** 6, 12
assert W * 2 ** b == 4_096_000_000
print("ALL CHECKS PASSED")