비밀번호는 사용자가 아는 하나의 비밀에 기댄다. 그 비밀 하나가 새어 나가면 계정이 그대로 넘어간다는 것이 비밀번호만으로 인증하는 방식의 근본적인 약점이다. 아무리 비밀번호를 강하게 만들고 안전하게 저장해도, 그것 하나에만 의존하는 한 그 하나가 뚫리면 방어가 무너진다. 2단계 인증은 여기에 성격이 다른 두 번째 확인을 더해, 하나가 뚫려도 나머지가 버티게 하는 방어다.


이번 편은 인증 수단을 나누는 세 가지 갈래가 무엇인지, 두 번째 수단으로 흔히 쓰이는 방식들이 각각 어떤 성질을 갖는지, 그중 어떤 것이 더 안전하고 어떤 것이 약한지, 그리고 두 번째 수단을 잃었을 때를 어떻게 대비하는지를 다룬다. 여러 수단을 겹치는 것이 방어를 어떻게 두껍게 만드는지를 이해하는 것이 목표다.

인증 수단을 나누는 세 갈래

인증 수단은 크게 세 갈래로 나뉜다. 첫째는 사용자가 아는 것이다. 비밀번호나 비밀 질문의 답처럼 머릿속에 있는 지식이 여기에 속한다. 둘째는 사용자가 가진 것이다. 특정 기기나 그 기기에 담긴 값처럼 손에 쥔 물건이 여기에 속한다. 셋째는 사용자 자신의 특징이다. 지문이나 얼굴처럼 몸에 딸린 성질이 여기에 속한다.


2단계 인증의 핵심은 이 서로 다른 갈래에서 두 가지를 요구하는 데 있다. 같은 갈래에서 둘을 요구하면, 하나가 뚫리는 상황이 다른 하나도 함께 뚫는 경우가 많다. 예컨대 비밀번호와 비밀 질문의 답은 둘 다 아는 것이라, 둘을 한꺼번에 알아내는 방식에 함께 노출된다. 반면 갈래가 다르면 하나를 뚫는 방식이 다른 하나에는 통하지 않는다.


그래서 두 번째 수단은 첫 번째와 다른 갈래에서 골라야 방어가 두꺼워진다. 아는 것에 더해 가진 것을 요구하면, 비밀번호가 새어 나가도 그 기기가 없으면 들어오지 못한다. 두 수단이 서로 다른 방식으로 뚫려야 하므로, 둘을 동시에 뚫는 일이 훨씬 어려워진다. 이 갈래의 분리가 여러 수단을 겹치는 방어의 바탕이다.


여러 수단을 겹친다고 해서 각 수단이 허술해도 되는 것은 아니다. 두 번째 수단이 있으니 비밀번호는 약해도 된다는 식의 태도는 위험하다. 각 수단은 저마다 튼튼해야 하고, 겹침은 그 위에 더해지는 방어다. 하나가 약하면 그만큼 전체 방어도 얇아지므로, 겹치기는 각 수단을 튼튼히 한 뒤에 얹는 것이다.

가진 것을 확인하는 방식들

두 번째 수단으로 가장 흔히 쓰이는 것이 사용자가 가진 기기를 확인하는 방식이다. 그 가운데 하나는 기기에서 주기적으로 바뀌는 짧은 코드를 만들어 내는 방식이다. 서비스와 기기가 같은 비밀을 공유하고, 현재 시각을 함께 계산해 같은 코드를 만들어 낸다. 사용자가 기기에 뜬 코드를 옮겨 적으면, 서비스는 자신이 계산한 코드와 대조해 그 기기를 가졌음을 확인한다.


이 방식의 코드는 짧은 시간마다 바뀐다. 코드가 곧 바뀌므로, 하나가 새어 나가도 통하는 시간이 매우 짧다. 코드를 만드는 비밀은 처음 설정할 때 한 번 기기에 담기고 그 뒤로는 오가지 않으므로, 매번 코드를 주고받는 방식보다 전송 중에 새어 나갈 여지가 적다. 시각에 기반해 양쪽이 각자 계산한다는 점이 이 방식의 안전을 떠받친다.


또 다른 방식은 서비스가 별도의 통로로 코드를 보내 주는 것이다. 문자 메시지로 코드를 보내는 방식이 대표적인데, 널리 쓰이지만 약점이 있다. 그 통로 자체가 가로채이거나, 통로를 관리하는 쪽을 속여 코드를 다른 곳으로 돌리는 방식에 노출될 수 있기 때문이다. 그래서 이 방식은 아예 두 번째 수단이 없는 것보다는 낫지만, 기기에서 코드를 만들어 내는 방식보다는 약한 것으로 여겨진다.


더 강한 방식으로는 별도의 물리적 장치를 쓰는 것이 있다. 이런 장치는 서비스와 직접 안전하게 주고받아 그 장치를 가졌음을 증명하며, 사용자가 코드를 옮겨 적을 필요도 없다. 옮겨 적는 과정이 없으므로, 사용자를 속여 코드를 가짜 화면에 입력하게 하는 방식에도 견딘다. 다루기가 조금 번거로운 대신 방어의 강도가 높다.

속여서 가로채는 것에 견디기

두 번째 수단을 두어도, 사용자를 속여 그 수단까지 함께 넘기게 만드는 방식은 남는다. 가짜 화면을 진짜처럼 꾸며, 사용자가 비밀번호와 두 번째 코드를 그곳에 입력하게 하고 그것을 곧바로 진짜 서비스에 흘려보내는 것이다. 이 방식 앞에서는 옮겨 적는 코드가 그대로 넘어갈 수 있다.


그래서 두 번째 수단의 강도를 따질 때는 이런 속임에 견디는지가 중요한 기준이 된다. 사용자가 코드를 옮겨 적는 방식은 그 코드가 가짜 화면으로 넘어갈 수 있어 이 속임에 약하다. 반면 사용자가 코드를 직접 다루지 않고 기기가 서비스와 직접 확인하는 방식은, 넘길 코드 자체가 없으므로 이 속임에 훨씬 강하다.


이 속임에 견디는 강한 방식은 대개 지금 접속한 곳이 진짜 서비스인지를 기기가 함께 확인한다. 사용자가 지금 어디에 접속해 있는지를 기기가 판단해, 가짜 화면에는 증명을 내주지 않는 것이다. 사용자의 판단에만 기대지 않고 기기가 대신 확인해 주므로, 사람이 속더라도 기기가 걸러 낸다.


모든 서비스가 가장 강한 방식만 쓸 수 있는 것은 아니므로, 현실에서는 여러 수단을 상황에 맞게 제공한다. 다만 각 수단의 강도 차이를 이해하고, 위험이 큰 계정일수록 속임에 강한 수단을 권하는 것이 방어의 원칙이다. 어떤 두 번째 수단이든 없는 것보다는 낫지만, 그 안에서도 강약이 있음을 알고 골라야 한다.

두 번째 수단을 잃었을 때

두 번째 수단을 도입하면 반드시 함께 다루어야 할 것이 그 수단을 잃었을 때의 대비다. 기기를 잃어버리거나 바꾸면 두 번째 수단에 접근하지 못하게 되는데, 이때 대비가 없으면 정당한 사용자가 자기 계정에서 영영 잠긴다. 방어를 두껍게 하려다 사용자를 가두는 일이 없도록, 잃었을 때의 길을 미리 마련해야 한다.


가장 흔한 대비는 미리 발급해 두는 예비 코드다. 두 번째 수단을 설정할 때 여러 개의 일회용 코드를 함께 발급해 사용자가 안전한 곳에 보관하게 하고, 기기를 잃었을 때 그중 하나로 들어오게 한다. 각 코드는 한 번만 쓰이므로, 쓴 코드는 폐기하고 남은 코드가 줄어들면 새로 발급하도록 안내한다.


이 예비 코드도 비밀이므로 비밀번호를 다루듯 저장해야 한다. 서버에는 원래 형태로 두지 않고 되돌릴 수 없는 형태로 바꾸어 보관하며, 사용자가 되돌려 준 코드를 같은 방식으로 바꿔 대조한다. 예비 코드가 새어 나가면 두 번째 수단을 우회하는 통로가 되므로, 발급과 보관을 신중히 한다.


복구 절차 자체가 두 번째 수단을 무력화하는 약한 고리가 되지 않도록 조심해야 한다. 잃었을 때의 복구를 지나치게 쉽게 만들면, 그 복구 경로가 곧 두 번째 수단을 건너뛰는 문이 된다. 그래서 복구에는 다른 확인 수단을 함께 요구하거나, 복구가 시도되었음을 사용자에게 알려 이상을 알아채게 하는 등의 방어를 겹친다.

언제 두 번째 수단을 요구할 것인가

두 번째 수단을 매 로그인마다 요구하면 안전하지만 번거롭다. 그래서 위험의 정도에 따라 요구 시점을 조절하는 설계가 쓰인다. 늘 요구하기보다, 위험이 높아 보이는 상황에서 특히 요구하는 방식으로 안전과 편의의 균형을 잡는다.


낯선 기기나 낯선 위치에서 로그인이 시도될 때가 두 번째 수단을 요구할 대표적인 시점이다. 늘 쓰던 기기에서의 로그인은 위험이 낮다고 보아 부담을 덜어 주고, 처음 보는 기기에서의 로그인은 위험이 높다고 보아 두 번째 수단을 요구하는 것이다. 상황의 위험을 가늠해 요구를 조절하면, 사용자의 부담을 줄이면서도 위험한 순간을 붙잡는다.


위험이 큰 동작 앞에서도 두 번째 수단을 요구한다. 비밀번호나 이메일 주소를 바꾸거나, 중요한 설정을 고치는 순간처럼 되돌리기 어려운 동작에서는, 로그인 상태가 유효하더라도 두 번째 수단을 다시 확인한다. 이런 동작이 도용된 세션으로 함부로 이루어지는 것을 막기 위해서다.


요구 시점을 조절하는 판단은 서버가 쥐고 있어야 한다. 어떤 상황을 위험하다고 볼지, 언제 두 번째 수단을 요구할지를 클라이언트의 주장에 맡기면, 그 판단이 조작될 수 있다. 위험을 가늠하고 요구를 결정하는 일은 서버에서 이루어져야, 두 번째 수단의 방어가 우회되지 않는다.

도입할 때 함께 챙길 것들

두 번째 수단을 도입할 때는 그 설정 과정 자체를 안전하게 다루어야 한다. 처음 두 번째 수단을 등록하는 순간, 그 등록이 진짜 계정 주인에 의한 것인지 확인해야 한다. 도용된 세션으로 두 번째 수단이 몰래 등록되면, 오히려 원래 주인이 밀려나는 일이 벌어질 수 있기 때문이다.


등록과 해제 시에는 사용자에게 알림을 보내는 것이 좋다. 두 번째 수단이 새로 등록되거나 해제되었다는 통지를 받으면, 그것이 자신이 한 일이 아닐 때 사용자가 이상을 알아챌 수 있다. 계정에 대한 중요한 변경은 사용자가 늘 알 수 있게 하는 것이 방어의 한 축이다.


여러 개의 두 번째 수단을 함께 등록하게 하는 것도 유용하다. 하나의 수단만 두면 그것을 잃었을 때 곧바로 곤란해지지만, 여러 수단을 두면 하나를 잃어도 다른 것으로 들어올 수 있다. 예비 코드와 함께 여러 수단을 마련해 두면, 잃음에 대한 대비가 한결 두꺼워진다.


두 번째 수단은 만능이 아니라 방어를 한 겹 더하는 장치임을 잊지 말아야 한다. 이것을 두었다고 다른 방어를 소홀히 하면, 두 번째 수단을 우회하는 약한 고리가 어딘가에 남는다. 비밀번호의 저장, 시도의 제한, 복구 경로의 방어가 모두 함께 튼튼해야, 두 번째 수단의 겹침이 제 값을 한다.


믿을 만한 기기를 기억하기

매 로그인마다 두 번째 수단을 요구하면 안전하지만, 늘 쓰던 기기에서까지 그러면 사용자의 피로가 쌓인다. 그래서 한 번 두 번째 수단을 통과한 기기를 일정 기간 믿을 만한 기기로 기억해, 그동안은 두 번째 수단을 다시 묻지 않는 절충이 쓰인다. 편의와 방어를 시간으로 나누어 얻는 방식이다.


이 기억은 그 기기에 표를 하나 남겨 두는 방식으로 이루어진다. 다음에 같은 기기에서 로그인하면 그 표를 확인해, 이미 두 번째 수단을 통과한 기기임을 알아본다. 다만 이 표도 새어 나가면 두 번째 수단을 건너뛰는 통로가 되므로, 다른 인증 값처럼 보호하고 수명을 두어 일정 기간이 지나면 다시 두 번째 수단을 요구해야 한다.


기억의 기간은 위험과 편의를 저울질해 정한다. 기간이 길면 편하지만 그 기기가 남의 손에 넘어갔을 때의 위험이 커지고, 짧으면 안전하지만 자주 다시 묻게 된다. 위험이 큰 서비스일수록 이 기간을 짧게 두고, 위험이 큰 동작 앞에서는 믿을 만한 기기라도 두 번째 수단을 다시 요구해 그 순간만큼은 건너뛰지 않게 한다.


사용자가 믿을 만한 기기의 목록을 직접 관리하게 하는 것도 좋다. 지금 어떤 기기들이 두 번째 수단을 건너뛰도록 기억되어 있는지 보여 주고, 그중 낯선 것을 사용자가 지울 수 있게 하면, 기기를 잃거나 남에게 넘겼을 때 스스로 그 기억을 거둘 수 있다. 기억의 편의를 주되 그 통제는 사용자에게 남기는 것이다.

정리하면 2단계 인증은 서로 다른 갈래에서 두 가지 수단을 요구해 하나가 뚫려도 나머지가 버티게 하는 방어다. 기기에서 코드를 만드는 방식이 별도 통로로 코드를 받는 방식보다 강하고, 사용자가 코드를 직접 다루지 않는 방식이 속임에 더 견딘다. 잃었을 때를 예비 코드로 대비하되 그 복구가 약한 고리가 되지 않게 하고, 위험한 상황과 동작에서 특히 요구한다. 다음 편에서는 로그인 이후의 세션이 언제 만료되고 어떻게 갱신되는지를 들여다본다.