비밀번호는 평문으로 저장하면 안 되고, 일반적으로 bcrypt, scrypt, Argon2 같은 password hashing 함수를 사용합니다. Salt는 같은 비밀번호라도 서로 다른 hash가 나오게 하는 랜덤 값입니다. 빠른 일반 hash만 쓰면 brute force나 rainbow table 공격에 약할 수 있습니다.
꼬리질문
조금 더 깊게 물어본다면
답변 뒤에 이어질 수 있는 질문들을 하나씩 열어볼 수 있어요.
왜 단순 SHA-256으로 저장하면 부족한가요?
SHA-256은 빠르게 계산되도록 설계되어 공격자가 대량 후보를 빠르게 시도할 수 있습니다. 비밀번호 저장에는 계산 비용을 의도적으로 높인 전용 함수가 더 적합합니다.
Rainbow table 공격이란?
자주 쓰이는 비밀번호와 그 hash 값을 미리 계산해 놓은 표를 이용해 hash에서 원문을 역추적하는 공격입니다. salt를 사용하면 사용자마다 hash 입력값이 달라져 미리 만든 표를 재사용할 수 없습니다.
Hashing과 encryption의 차이는?
Hashing은 원문으로 되돌릴 수 없는 단방향 변환이고, encryption은 key가 있으면 복호화할 수 있는 양방향 변환입니다. 비밀번호는 복호화할 필요가 없어 hashing이 적합합니다.
Salt는 비밀로 숨겨야 하나요?
숨기지 않아도 됩니다. salt의 목적은 비밀성이 아니라 같은 비밀번호를 쓰는 사용자들의 hash를 서로 다르게 만들고 rainbow table 재사용을 막는 것입니다.
Pepper는 무엇인가요?
salt와 달리 DB가 아닌 애플리케이션 서버에 별도로 보관하는 비밀 값입니다. DB만 유출된 경우 추가 방어층이 될 수 있지만 관리 책임이 크고, 분실 시 복구가 어렵습니다.
Salt는 어디에 저장하나요?
일반적으로 hash 결과와 함께 같은 DB 컬럼에 저장합니다. bcrypt 같은 함수는 salt를 hash 결과 문자열 안에 포함시켜 별도 컬럼 없이도 관리할 수 있습니다.
비밀번호 검증은 어떻게 하나요?
로그인 시 입력된 비밀번호와 저장된 salt, cost 정보를 사용해 hash를 다시 계산하고 저장된 hash와 비교합니다. 일치하면 같은 비밀번호입니다.
bcrypt, argon2 같은 함수를 쓰는 이유는?
일반 hash 함수와 달리 계산 비용을 조절하는 cost factor를 지원합니다. 하드웨어가 빨라져도 cost를 높여 공격자의 대량 시도 속도를 일정 수준으로 억제할 수 있습니다.
부가 설명
로그인 기능을 만들 때 비밀번호를 다시 보여줄 일은 없습니다. 서버가 해야 하는 일은 사용자가 입력한 비밀번호가 맞는지 검증하는 것입니다. 그래서 복호화 가능한 방식으로 저장하기보다, 입력값을 같은 방식으로 hash해 저장된 hash와 비교합니다.
Salt는 같은 비밀번호를 쓰는 사용자들이 같은 hash를 갖지 않게 만듭니다. 여기에 password hashing 함수는 일부러 계산 비용을 높여 대량 추측을 어렵게 합니다. SHA-256 같은 빠른 일반 hash와 password hashing 함수는 목적이 다릅니다.
한 줄 정리
비밀번호 저장의 목표는 다시 읽는 것이 아니라 맞는지 검증하면서 원문 추측을 어렵게 만드는 것입니다.