인증 앱의 6자리 숫자는 어떻게 만들어질까? OTP와 2단계 인증
은행 앱이나 회사 시스템에 로그인하다 보면 비밀번호 다음에 한 단계가 더 나옵니다. 인증 앱을 열어 30초마다 바뀌는 6자리 숫자를 입력하라는 요구입니다. 그런데 이 숫자는 어디서 오는 걸까요? 폰은 서버와 통신하는 기색도 없이 숫자를 척척 만들어 내고, 비행기 모드에서도 멀쩡히 갱신됩니다. 이번 글에서는 이 6자리 숫자의 정체와 2단계 인증이 실제로 막아 주는 것을 코드 없이 정리하겠습니다.
2단계 인증이 막는 것 #
비밀번호는 생각보다 자주 샙니다. 다른 사이트에서 유출된 비밀번호를 그대로 넣어 보는 공격도 있고, 가짜 로그인 페이지에 속아 직접 입력해 버리는 일도 있습니다. 비밀번호 하나로만 잠근 계정은 그 한 줄이 새는 순간 끝입니다.
2단계 인증은 잠금장치를 하나 더 다는 것이 아니라, 종류가 다른 잠금장치를 다는 것입니다. 비밀번호는 머릿속에 든 “아는 것"이고, 인증 앱이 설치된 폰은 손에 쥔 “가진 것"입니다. 공격자가 비밀번호를 알아내도 내 폰까지 손에 넣지는 못했으므로 문은 열리지 않습니다. 두 가지가 동시에 뚫려야 하는 구조라서, 한쪽이 새도 계정은 버팁니다. 참고로 비밀번호 확인 이후에 로그인 상태가 어떻게 유지되는지는 쿠키, 세션, 토큰 이야기에서 따로 정리했습니다.
QR코드를 찍는 순간 일어나는 일 #
2단계 인증을 켤 때 화면에 뜬 QR코드를 인증 앱으로 찍습니다. 이 행위의 정체는 의외로 단순합니다. 비밀 열쇠 하나를 서버와 폰이 나눠 갖는 것입니다.
QR코드 안에는 그 계정 전용으로 만들어진 긴 무작위 문자열이 들어 있습니다. 서버는 이 문자열을 자기 금고에 보관하고, 폰의 인증 앱도 같은 문자열을 받아 저장합니다. 이 순간부터 세상에서 이 열쇠를 아는 것은 서버와 내 폰, 둘뿐입니다. QR코드는 긴 문자열을 손으로 칠 필요 없이 카메라로 옮겨 적는 수단일 뿐이고, “코드를 입력해 등록"을 누르면 같은 문자열을 직접 타이핑할 수도 있습니다.
그래서 이 QR코드는 일회용 입장권이 아니라 열쇠 원본의 복사본입니다. 등록 화면을 캡처해 두면 누구든 같은 열쇠를 가질 수 있으므로, 등록이 끝난 QR코드 화면은 남겨 두지 않는 편이 안전합니다.
6자리 숫자가 만들어지는 원리 #
이제 본론입니다. 서버와 폰은 같은 비밀 열쇠를 갖고 있고, 둘 다 시계를 갖고 있습니다. 이 두 가지면 충분합니다.
인증 앱은 비밀 열쇠와 현재 시각을 정해진 계산식에 넣습니다. 계산 결과로 나온 긴 값에서 6자리만 잘라낸 것이 화면의 숫자입니다. 서버도 검증할 때 똑같이 합니다. 자기 금고의 비밀 열쇠와 자기 시계의 현재 시각을 같은 계산식에 넣어 6자리를 만들고, 사용자가 입력한 숫자와 비교합니다. 같은 재료를 같은 식에 넣었으니 답도 같습니다. 양쪽이 약속이나 한 듯 같은 숫자를 떠올리는 비밀이 이것입니다.
시각은 30초 단위로 끊어서 씁니다. 10시 0분 0초부터 30초 동안은 같은 시각으로 치고, 30초가 지나면 다음 칸으로 넘어갑니다. 숫자가 30초마다 바뀌는 이유가 여기 있습니다. 이 방식을 시간 기반 일회용 비밀번호, 줄여서 TOTP라고 부르는데 이름까지 외울 필요는 없습니다. 한 번 쓰고 버리는 답을 시계로 만들어 낸다는 발상만 기억하면 충분합니다.
계산식은 한 방향으로만 동작합니다. 비밀 열쇠로 6자리를 만들기는 쉽지만, 6자리를 보고 비밀 열쇠를 거꾸로 알아내기는 사실상 불가능합니다. 그래서 누가 어깨너머로 지금 숫자를 보더라도, 30초 뒤의 숫자는 알 수 없습니다.
인터넷 없이도 되는 이유 #
비행기 모드에서도 인증 앱의 숫자가 갱신되는 것을 보고 의아했던 적이 있을지도 모릅니다. 원리를 알고 나면 당연한 일입니다. 폰은 서버에서 숫자를 받아 오는 것이 아니라, 자기 안에 저장된 비밀 열쇠와 자기 시계로 직접 계산합니다. 서버도 자기 쪽에서 따로 계산합니다. 둘은 통신하지 않고 각자 계산해서 답을 맞춰 보는 관계입니다. 그래서 폰에 데이터가 안 터지는 해외에서도, 와이파이가 없는 지하에서도 인증 앱은 동작합니다.
남는 걱정은 시계입니다. 폰 시계가 서버 시계와 어긋나면 양쪽의 계산 결과도 달라질 텐데, 다행히 여기에는 여유가 있습니다. 서버는 보통 바로 앞뒤 30초 칸의 답까지 함께 인정해 줍니다. 시계가 1분 가까이 어긋난 게 아니라면 인증은 통과합니다. 인증 앱 숫자가 자꾸 틀린다고 나오면 폰의 날짜와 시간을 자동 설정으로 맞추라는 안내가 따라오는데, 그 배경이 바로 이 시계 맞추기입니다.
SMS 인증과 무엇이 다를까 #
문자 메시지로 인증번호를 받는 SMS 인증도 같은 “가진 것” 확인처럼 보입니다. 그런데 둘 사이에는 중요한 차이가 있습니다. SMS 인증번호는 서버가 만들어서 통신망을 거쳐 배달되는 숫자이고, 인증 앱의 숫자는 폰 안에서 태어나는 숫자입니다.
배달에는 가로챌 틈이 생깁니다. 대표적인 수법이 심 스와핑입니다. 공격자가 통신사를 속여 피해자의 전화번호를 자기 유심으로 옮겨 버리면, 그 순간부터 인증 문자가 공격자의 폰으로 배달됩니다. 전화번호는 내 소유물 같지만 실제로는 통신사가 관리하는 설정값이라서, 그 설정이 넘어가면 “가진 것” 인증도 함께 넘어갑니다. 인증 앱은 이 경로 자체가 없습니다. 비밀 열쇠가 폰 밖으로 나가지 않고 숫자도 배달되지 않으므로, 전화번호를 빼앗겨도 6자리는 만들 수 없습니다. SMS 인증이 없는 것보다는 훨씬 낫지만, 고를 수 있다면 인증 앱이 한 수 위인 이유입니다.
백업 코드를 적어 두라고 하는 이유 #
2단계 인증을 켜면 서비스가 백업 코드 몇 개를 보여 주며 안전한 곳에 보관하라고 합니다. 귀찮아서 건너뛰기 쉽지만, 원리를 알면 그냥 넘길 수 없습니다. 비밀 열쇠는 폰 안에만 있으므로, 폰을 잃어버리면 열쇠도 함께 사라집니다. 비밀번호는 기억하고 있어도 “가진 것” 단계를 통과할 방법이 없어져, 내 계정에 내가 못 들어가는 상황이 됩니다.
백업 코드는 이때를 위한 비상 열쇠입니다. 한 번 쓰면 사라지는 일회용이고, 인증 앱 없이도 그 단계를 통과하게 해 줍니다. 폰과 같은 곳에 두면 의미가 없으므로 종이에 적어 따로 보관하거나, 비밀번호 관리 도구처럼 폰과 운명을 같이하지 않는 곳에 넣어 두는 것이 요령입니다. 폰을 바꿀 때도 마찬가지입니다. 새 폰으로 인증 앱을 옮기는 절차를 마치기 전에 옛 폰을 초기화하면 같은 일이 벌어집니다.
다음 단계, 패스키 #
요즘 로그인 화면에서 자주 보이는 패스키는 이 흐름의 다음 단계입니다. 비밀번호 없이 폰이나 컴퓨터에 저장된 열쇠와 지문, 얼굴 인식만으로 로그인하는 방식인데, 6자리를 옮겨 적는 수고가 없고 가짜 사이트에 속아 입력해 버릴 숫자 자체가 없습니다. 아직 모든 서비스가 지원하지는 않으므로, 당분간은 비밀번호와 인증 앱의 조합이 가장 현실적인 기본기입니다.
마무리 #
정리하면 이렇습니다. 2단계 인증은 “아는 것"과 “가진 것"을 겹쳐 한쪽이 새도 버티게 만드는 장치입니다. QR코드 등록은 비밀 열쇠를 서버와 폰이 나눠 갖는 절차이고, 6자리 숫자는 그 열쇠와 현재 시각을 양쪽이 같은 계산에 넣어 각자 얻는 답입니다. 통신 없이 각자 계산하므로 비행기 모드에서도 동작하고, 배달 과정이 없으므로 SMS 인증보다 안전합니다. 다음에 인증 앱의 숫자가 30초를 다 채우고 바뀌는 순간, 그 뒤에서 폰과 서버가 같은 답을 떠올리고 있다는 사실을 기억해 주시기 바랍니다.