🧂 솔트 없는 일방향 해시 KISA A-2 · 솔트 없는 일방향 해시
무솔트 MD5/SHA로 저장된 비밀번호 테이블이 유출되었습니다. 두 가지 결과: 동일 비밀번호는 동일 해시가 되어(재사용이 드러남), 미리 계산된 레인보우 테이블이 흔한 해시를 즉시 역산합니다. 사용자별 솔트 + 느린 KDF(bcrypt/argon2)가 둘 다 막습니다.
① 유출 DB: 무솔트 해시 VULNERABLE
한 줄에 한 명씩
아이디:비밀번호 형식으로 입력하세요. 앱은 솔트 없이 hash(비밀번호)를 저장합니다. 중복 비밀번호가 어떻게 드러나는지 확인하세요.
② 안전한 DB: 사용자별 솔트 + 느린 KDF SECURE
동일한 비밀번호를 사용자별 무작위 솔트와 함께 느린 KDF(bcrypt)로 저장합니다. 이제 같은 비밀번호도 다른 해시가 되고, 레인보우 테이블은 전부 빗나가며, 무차별 대입은 work factor로 느려집니다.
③ 취약 vs 안전 코드
VULNERABLE
# Python — 무솔트 빠른 해시
import hashlib
def store(pw):
# 솔트 없음 + 빠른 해시 → 레인보우/무차별에 취약
return hashlib.md5(pw.encode()).hexdigest()
# 같은 pw → 같은 해시, GPU로 초당 수십억회 시도
db[user] = store(password)
SECURE
# Python — 사용자별 솔트 + 느린 KDF
import bcrypt
def store(pw):
salt = bcrypt.gensalt(rounds=12) # 무작위 솔트 내장
return bcrypt.hashpw(pw.encode(), salt)
def check(pw, stored):
return bcrypt.checkpw(pw.encode(), stored)
# 같은 pw → 매번 다른 해시, 의도적으로 느림(argon2id도 권장)
방어 핵심: 비밀번호에 원시 MD5/SHA 금지 · 사용자별 무작위 솔트와 함께 메모리-하드/느린 KDF(argon2id, bcrypt, scrypt, PBKDF2) 사용(KDF가 솔트를 내장) · work factor 튜닝 · 서버측 pepper를 시크릿 저장소에 추가(선택) · 로그인 시도 rate-limit·모니터링.
⚠️ 교육용 시뮬레이션입니다. 여기서 쓰는 해시는 작은 결정적 mock이며 실제 MD5가 아닙니다. 레인보우 테이블도 개념 설명용 소형 내장 lookup입니다.