비밀번호 재사용 금지 설계 면접: 오백 명이 쓰는 비밀번호를 어떻게 세나
시스템 디자인 Vol.1 · 22장 「이 비밀번호를 오백 명이 쓰고 있습니다」에서
이런 화면입니다
비밀번호 변경 화면에 규칙 셋이 붙습니다. 최근에 쓴 세 개로는 못 바꾸고, 여섯 달 안에 쓴 값으로도 못 바꾸고, 이미 오백 개 이상의 계정이 쓰는 값으로도 못 바꿉니다.
서비스는 비밀번호 자체를 저장하지 않습니다. 이 사실이 세 규칙에 각각 어떤 영향을 주는지가 면접관이 보는 곳입니다.
면접관이 이렇게 묻습니다
계정이 6,000만 개인 서비스입니다. 비밀번호 변경에 규칙 셋을 걸어야 합니다. 최근 세 개 금지, 여섯 달 안에 쓴 값 금지, 오백 개 이상의 계정이 쓰는 값 금지입니다. 설계해 보세요.
범위부터 좁힙니다
먼저 서비스가 저장하는 것을 짚습니다. 저장하는 것은 비밀번호 원문 대신, 한 방향으로만 계산되는 요약값입니다. 그 요약값에는 사람마다 다른 소금(salt)이 섞여 있습니다.
세 규칙을 이 저장 방식 위에서 각각 어떻게 답할지가 핵심 질문입니다.
가장 많이 나오는 답
셋 다 쿼리 한 줄로 답합니다. 오백 계정 규칙은 같은 요약값을 가진 계정 수를 셉니다.
SELECT COUNT(*) FROM credentials
WHERE password_hash = :newHash; -- 500 이상이면 거절
쿼리 모양만 보면 그럴듯합니다.
그런데 여기서 깨집니다
소금 때문에 같은 비밀번호를 쓰는 두 사람의 저장값이 서로 다릅니다. 이 쿼리가 세는 값은 언제나 0 아니면 1입니다. 규칙이 한 번도 작동하지 않습니다.
그렇다고 소금을 없애면 저장값이 새어 나갔을 때 한 사람을 푼 노력이 모든 사람에게 재활용됩니다. 소금은 바로 그 일을 막으려고 있습니다.
떨어지는 답은 이런 모양입니다
- 셋 다 쿼리 한 줄로 끝내고, 그 수가 언제나 1이라는 것을 짚지 못합니다.
- 소금을 없애자고 답합니다.
- 옛 비밀번호를 원문으로 저장해 두자고 답합니다.
- 검사 한 번에 드는 비용을 재지 않습니다.
면접관은 여기서 멈추지 않습니다
소금을 빼면 셀 수 있지 않나요?
보안 목적을 깨는 답을 스스로 알아채는지 봅니다.
옛 비밀번호를 원문으로 남겨 두면 비교가 쉽지 않나요?
편한 답이 만드는 더 큰 위험을 말하는지 봅니다.
6,000만 계정에서 이 검사를 한 번 하는 데 비용이 얼마나 드나요?
설계를 비용으로 재 보는 습관이 있는지 봅니다.
이 다음 판단은 책에서 이어집니다
책은 세 규칙이 각각 무엇을 읽어야 하는지 따지고, 저장 방식을 지키면서 오백 계정 규칙을 어떻게 다룰지 정합니다. 그 판단이 놓이는 테이블과 넣지 말아야 할 데이터까지 이어집니다.
22장에서 이어지는 것
- 세 규칙이 각각 읽어야 하는 것
- 소금을 지키면서 오백 계정을 다루는 방법
- 검사 한 번의 비용
- 넣지 말아야 할 데이터