비밀번호를 그대로 저장하면 안 되는 이유 (해시 함수와 솔팅)
데이터베이스가 해킹당했다는 뉴스를 종종 접하게 됩니다.
이때 "비밀번호가 암호화되어 있어 안전하다"라는 문구를 보신 적이 있나요? 엄밀히 말하면 이는 틀린 표현입니다. 비밀번호는 '암호화(Encryption)'하는 것이 아니라 **'해싱(Hashing)'**해야 하기 때문입니다.
암호화와 해싱의 차이, 그리고 왜 MD5나 SHA-1 같은 해시 함수를 쓰면 안 되는지 알아보겠습니다.
1. 암호화 vs 해싱
가장 큰 차이점은 **"복호화 가능 여부"**입니다.
- 암호화 (Encryption): 키를 사용하여 데이터를 변환하며, 키가 있으면 다시 원본으로 되돌릴 수 있습니다. (양방향)
- 해싱 (Hashing): 데이터를 고정된 길이의 문자열로 변환하며, 원본으로 되돌릴 수 없습니다. (단방향)
비밀번호는 서버 관리자조차 알 필요가 없으며, 알면 안 되는 정보입니다. 따라서 복호화가 불가능한 해싱을 사용해야 합니다.
2. 레인보우 테이블 공격
"그럼 SHA-256 같은 해시 함수를 쓰면 안전하겠네요?"
아쉽게도 그렇지 않습니다. 해시 함수는 같은 입력에 대해 항상 같은 출력을 내놓습니다.
해커들은 미리 123456, password 같은 흔한 비밀번호들의 해시값을 모두 계산하여 표로 만들어 둡니다. 이를 **레인보우 테이블(Rainbow Table)**이라고 합니다.
DB에서 해시된 비밀번호를 탈취한 뒤, 이 테이블과 대조하면 원본 비밀번호를 순식간에 찾아낼 수 있습니다.
3. 소금 치기 (Salting)
이 문제를 해결하기 위해 등장한 것이 **솔팅(Salting)**입니다.
비밀번호를 해싱하기 전에, 랜덤한 문자열(Salt)을 앞이나 뒤에 붙여서 해싱하는 것입니다.
Hash("password") -> 위험
Hash("password" + "random_salt_value") -> 안전
이렇게 하면 같은 비밀번호라도 사용자마다(Salt가 다르므로) 다른 해시값이 생성되어, 레인보우 테이블 공격을 무력화할 수 있습니다.
결론
비밀번호 저장에는 단순한 해시 함수(MD5, SHA-1, SHA-256)를 사용해서는 안 됩니다. 이들은 너무 빨라서 무차별 대입 공격에 취약합니다.
대신, 솔팅과 키 스트레칭(Key Stretching)이 적용된 전용 알고리즘을 사용해야 합니다.
- 추천 알고리즘: Argon2, bcrypt, scrypt, PBKDF2
보안은 "뚫리지 않는 것"이 아니라 "뚫는 데 드는 비용을 높이는 것"입니다. 올바른 해싱 알고리즘 사용은 그 비용을 천문학적으로 높여줍니다.
관련 도구 둘러보기
Pockit의 무료 개발자 도구를 사용해 보세요