수수한 하드웨어에서 비밀번호가 치르는 값
이 글의 내용
여기 통계 페이지는 비밀번호로 보호할 수 있습니다. 그 비밀번호를 해시하는 것은 이 서비스에서 유일하게 느려야 마땅한 연산입니다 — 훔친 해시를 공격하는 값을 비싸게 만드는 것이 그것이니까요. 물음은 이 하드웨어에서 얼마나 느리냐는 것입니다.
이 사이트를 돌리는 기계에서, PHP 8로 잰 값입니다:
PASSWORD_DEFAULT | 560ms | (cost 12로 정해짐) |
| cost 12 | 595ms | |
| cost 11 | 277ms | |
| cost 10 | 138ms |
bcrypt의 cost 매개변수는 지수입니다. 한 단계마다 일이 두 배가 됩니다. 측정값이 바로 그 두 배를 보여 주며, 다른 무엇이 끼어들지 않았다는 좋은 신호입니다.
왜 기본값이 여기서는 잘못된 선택인가
PHP는 bcrypt의 기본 cost를 10에서 12로 올렸습니다. 데스크톱 서버라면 분별 있는 개선입니다 — 수십 밀리초 문제입니다. 수수한 하드웨어에서는 순수 프로세서 시간으로 반 초가 넘고, 그 기계는 동시에 다른 모두를 위해 카운터 그림을 그리고 있습니다.
로그인마다 반 초는 그 자체로 나쁩니다. 초대장으로는 더 나쁩니다. 누구나 로그인 지점을 부를 수 있고, 부를 때마다 사이트 전체를 떠받치는 프로세서의 560ms를 씁니다. 그러면 비밀번호 검증이 가장 값싼 서비스 거부 공격면이 됩니다.
그래서 cost는 기본값에 맡기지 않고 10에 못 박았습니다. PHP가 지금 고르는 것보다 일부러 약하며, 묻어 두기보다 분명히 말해 두어야 합니다. cost 10 해시는 cost 12 해시보다 공격하는 값이 4분의 1입니다. 그것을 되사는 것은 이 비밀번호가 실제로 지키는 대상입니다 — 방문 수가 적힌 페이지의 노출이지, 계정도 돈도 신원도 아닙니다. 그 뒤에 빼앗을 것이 없습니다.
놓치기 쉬운 대목
PASSWORD_DEFAULT은 설계상 움직이는 값입니다. 몇 해 전에 그것으로 쓰인 코드는 PHP를 올릴 때마다 소리 없이 느려집니다 — 같은 소스, 같은 입력, 몇 배의 실행 시간. 의도된 동작이고, 대부분의 소프트웨어에서는 그것이 옳습니다.
잘못되는 것은 기계가 그것을 감당하지 못할 때뿐이고, 감당하지 못할 때 아무것도 경고하지 않습니다. 업그레이드는 성공하고, 시험은 통과하고, 페이지는 여전히 작동합니다. 그저 반 초 더 걸릴 뿐이고, 재 보러 가지 않는 한 아무도 그 숫자를 보지 않습니다.