당신의 비밀번호가 정말로 깨지는 데 걸리는 시간

게시일 글쓴이 David Carrero

어떤 사이트가 당신의 비밀번호를 깨는 데 300만 년이 걸린다고 말할 때, 그 문장은 가장 중요한 부분을 빼먹고 있습니다. 올바른 질문은 얼마나 걸리느냐가 아닙니다. 무엇에 맞서서 얼마나 걸리느냐입니다.

그리고 그 무엇에 맞서서를 정하는 사람은 당신이 아닙니다. 2019년에 운동화 한 켤레 샀던 그 쇼핑몰의 개발자가 정했습니다. 당신의 비밀번호를 데이터베이스에 어떻게 저장할지 고르던 순간에요. 당신은 두 사이트에 똑같은 스무 글자를 쳤습니다. 한쪽에서는 수백 년을 버티고, 다른 쪽에서는 점심시간 전에 무너집니다.

방정식에서 빠진 숫자

무차별 대입 공격은 초등학교 산수입니다. 시도해봐야 할 후보의 수를, 초당 시도할 수 있는 후보의 수로 나눈 것. 앞의 항은 당신의 비밀번호에 달려 있습니다. 길이, 문자 집합, 사전에 실려 있는 단어인지 아닌지. 뒤의 항은 당신과 아무런 상관이 없습니다.

뒤의 항은 두 가지에 달려 있습니다. 공격자의 하드웨어, 그리고 무엇보다도 그 사이트가 당신의 비밀번호를 사용자 테이블에 들어갈 알아볼 수 없는 문자열로 바꿀 때 쓴 함수. 그 함수를 해시라고 부르는데, 계산 비용이 다 같지 않습니다.

MD5와 SHA-1은 빠르라고 설계됐습니다. 그건 장점입니다. 범용 해시 함수이고, 메시지를 요약하고 무결성을 확인하는 용도이며, 거기서 원하는 건 커피 타러 일어날 틈도 없이 1기가바이트를 처리하는 겁니다. 누군가 그걸 비밀번호 저장에 쓰는 순간, 그 장점이 문제로 바뀝니다. 초당 수백만 번 계산할 수 있는 함수는 공격자도 초당 수백만 번 계산할 수 있는 함수입니다. 그쪽에는 그래픽카드가 있고 주말이 통째로 있습니다.

bcrypt와 Argon2는 정반대의 목표로 설계됐습니다. 일부러 느리고, 그리고 — 여기가 우아한 대목인데 — 느린 정도를 조절할 수 있습니다. Niels Provos와 David Mazières는 1999년에 bcrypt를 발표하면서 제목에 전부를 담았습니다. 「A Future-Adaptable Password Scheme」. 하드웨어가 싸지는 속도에 맞춰 함수를 해마다 더 비싸게 만들 수 있다는 발상이었습니다. 2015년 Password Hashing Competition에서 우승한 Argon2는 한 겹을 더 얹었습니다. 시간만 드는 게 아니라 메모리가 듭니다. 하필 GPU가 가장 인심 좋게 내주지 못하는 자원이죠.

빠른 해시와 잘 설정된 느린 해시 사이에는 몇 퍼센트의 차이가 있는 게 아닙니다. 자릿수의 차이가 있습니다. 그것도 여러 자리요.

벤치마크는 존재하고, 공개돼 있다

추측이 아닙니다. 세상 절반이 비밀번호를 깨는 데 쓰는 도구 hashcat은 — 좋은 편에 선 사람들도 씁니다 — 벤치마크 모드를 갖고 있습니다. 누구나 자기 컴퓨터에서 돌려서 알고리즘별로 초당 몇 번 계산되는지 직접 잴 수 있습니다. 새 GPU가 나올 때마다 커뮤니티가 그 표를 올립니다.

그 표에서 흥미로운 건 어떤 구체적인 숫자가 아닙니다 — 그건 하드웨어 세대가 바뀌면 어차피 유통기한이 지납니다 — 행과 행 사이의 거리입니다. 속도순으로 정렬하면 맨 위에, 혼자만의 행성에 MD5가 있습니다. 내려가고 또 내려가면 표 밑바닥에 bcrypt와 Argon2가 있고, 그 숫자들은 위쪽과 닮은 구석이 하나도 없습니다. 같은 비밀번호입니다. 같은 GPU입니다. 달라진 건 사이트가 그걸 어떻게 저장하기로 했느냐뿐입니다.

그래서 어떤 해시에 맞선 건지 말하지 않는 「300만 년」은 측정값이 아니라 광고 문구입니다. 목적지는 말하지 않은 채 우리 차는 여섯 시간이면 도착한다고 자랑하는 것과 같습니다.

오프라인과 온라인: 서로 닿지 않는 두 세계

거의 아무도 설명하지 않지만 결과를 그만큼이나 난폭하게 바꾸는 두 번째 구분이 있습니다.

온라인 공격에서 공격자는 로그인 창에 비밀번호를 넣어봅니다. 보통 사용자가 하듯이요. 속도를 정하는 건 그의 하드웨어가 아니라 서버입니다. 시도 횟수 제한이 있을 수 있고, 일시 잠금이 있을 수 있고, 캡차가 있을 수 있고, 요청 사이의 지연이 있을 수 있고, 같은 주소에서 천 번 실패하면 경보가 울릴 수 있습니다. 어지간히 방어된 사이트를 상대로 온라인 공격은 느리고, 시끄럽고, 꽤 멍청한 짓입니다. 공격자 입장에서 산수가 워낙 안 맞아서 순수한 무차별 대입은 거의 시도조차 하지 않습니다. 늘 그 뻔한 비밀번호 네 개를 수백만 개의 계정에 넣어보죠. 그건 다른 게임입니다.

오프라인 공격에서 공격자는 이미 데이터베이스 덤프를 갖고 있습니다. 그걸 집으로 가져갑니다. 거기엔 서버도, 시도 제한도, 지켜보는 사람도 없습니다. 그의 그래픽카드와 그의 전기요금 고지서가 있을 뿐입니다. 아무도 모르게 몇 달이고 시도할 수 있고, 맞혔다는 것도 혼자서 해시를 대조해 알아냅니다. 여기서는 해시가 전부를 결정합니다. 해시가 말 그대로 그를 막는 유일한 것이니까요.

확률에 대해서는 솔직해질 필요가 있습니다. 오프라인 시나리오는 이국적인 이야기가 아닙니다. 데이터베이스가 유출될 때마다 벌어지는 일입니다. LinkedIn이 2012년에 자기 것을 잃어버렸을 때, 공개된 덤프를 분석해보니 비밀번호가 SHA-1로, 그것도 솔트 없이 저장돼 있었습니다. 빠른 해시에, 표를 미리 계산해두는 걸 막아주는 재료마저 빠진 겁니다. 그렇게 많이, 그렇게 빨리 깨진 게 사용자들이 비밀번호를 잘못 골랐기 때문만은 아니었습니다. 무엇보다도, 어떤 사용자도 본 적 없는 엔지니어링 결정 때문이었습니다.

우리가 여기서 하는 일, 그리고 그걸 밝히는 이유

우리 검사기초당 10¹² 회 시도, 오프라인, 빠른 해시를 가정합니다. 결과 바로 아래, 그 페이지에 적혀 있습니다. 장식용 투명성 때문이 아닙니다. 그 정보가 없으면 화면에 뜬 시간은 아무 의미가 없기 때문입니다.

일부러 나쁜 쪽의 경우입니다. 데이터베이스는 이미 유출됐고, 공격자는 제대로 된 하드웨어를 갖고 있고, 사이트는 상식적으로 가능한 최악의 방식으로 당신의 비밀번호를 저장했고, 게다가 당신이 쓴 문자 집합과 길이까지 안다고 가정합니다. 그 사이트가 bcrypt를 잘 설정해 썼다면 실제 숫자는 자릿수가 몇 개나 올라가고, 당신의 비밀번호는 우리가 말한 것보다 훨씬 오래 버팁니다.

우리는 그쪽으로 틀리는 편을 택합니다. 당신을 칭찬하는 검사기는 자기 자신을 칭찬하고 있는 겁니다.

불편한 결론

당신의 비밀번호에는 깨지는 시간이 하나로 있지 않습니다. 그걸 써본 사이트마다 하나씩 있고, 그 시간을 정하는 건 당신이 모르는 사람들이 공개하지 않는 기준으로 정합니다.

여기서 두 가지가 따라 나오는데, 늘 그 두 가지입니다. 첫째, 해시를 통제할 수 없으니 엔트로피를 통제하세요. 방정식에서 당신 몫인 절반이 그것입니다 — 생성기가 상냥한 퍼센트 대신 비트를 보여주는 이유입니다 —. 둘째, 그리고 더 중요하게, 사이트마다 비밀번호가 다르면 MD5로 저장해둔 그 사이트는 그 사이트의 비밀번호밖에 넘겨줄 게 없습니다.

약한 고리는 당신의 비밀번호가 아니니까요. 당신이 그걸 쳐 넣은 최악의 사이트입니다.


출처: hashcat의 공개 벤치마크(hashcat -b), 누구나 확인하고 재현할 수 있음 · N. Provos, D. Mazières, 「A Future-Adaptable Password Scheme」, USENIX, 1999 · Password Hashing Competition, 2015년 Argon2 우승 · password.es 검사기가 명시한 위협 모델: 초당 10¹² 회 시도, 오프라인, 빠른 해시 · 2012년 LinkedIn 유출 사고: 회사가 유출을 확인했고, 솔트 없는 SHA-1 사용은 공개된 덤프를 분석하면서 확인됨.

← 블로그로 돌아가기