한양과학기술고등학교

에듀테크 프로젝트 대시보드

2단계 인증 (TOTP)

2단계 인증 (TOTP)

Google Authenticator 앱에 뜨는 6자리 숫자는 어디서 오고, 서버는 그걸 어떻게 검증할까? · RFC 6238

1. 비밀번호 하나로는 왜 부족한가

비밀번호는 유출·재사용·피싱에 약하다. 그래서 로그인에 서로 다른 종류의 근거를 두 개 이상 요구한다. 이것이 다중 요소 인증(MFA)이고, 그중 가장 흔한 두 번째 요소가 30초마다 바뀌는 숫자 코드다.

🧠
지식 (Knowledge) 아는 것 — 비밀번호, PIN
📱
소유 (Possession) 가진 것 — 휴대폰, 보안 키, OTP 앱
🫆
존재 (Inherence) 그 자체인 것 — 지문, 얼굴

TOTP(Time-based One-Time Password)는 소유 요소를 증명한다. 서버와 앱이 최초 등록 때 비밀 키(secret) 하나를 공유해 두면, 이후에는 네트워크로 그 키를 주고받지 않고도 양쪽이 같은 코드를 독립적으로 계산할 수 있다.

2. 핵심 아이디어: 공유 비밀 + 현재 시각

코드를 만드는 재료는 딱 두 가지다.

  • 공유 비밀 키 — QR 코드를 스캔할 때 앱에 저장된다 (보통 Base32 문자열).
  • 현재 시각을 30초 단위로 자른 카운터 T = ⌊(현재 유닉스 시각) / 30⌋

이 둘을 HMAC-SHA1에 넣어 20바이트 해시를 얻고, 거기서 동적 절단(Dynamic Truncation)으로 6자리를 뽑는다. 시각이 재료이므로 30초가 지나면 자동으로 다른 코드가 되고, 시간은 흐르기만 하므로 같은 코드는 다시 쓰이지 않는다(one-time).

3. 직접 만들어 보기

아래는 브라우저의 Web Crypto API로 실제 RFC 6238 알고리즘을 돌린다. 서버로 아무것도 보내지 않는다.

------ --s

이 키와 같은 값을 넣은 OTP 앱이라면 세계 어디서든 지금 이 순간 같은 6자리를 표시한다.

계산 과정 (현재 시간 단계)

HMAC-SHA1 20바이트 → 동적 절단

마지막 바이트의 하위 4비트 = 오프셋. 그 위치부터 4바이트를 읽어 최상위 비트를 0으로 만든 뒤 % 1,000,000 → 6자리.

4. 서버는 어떻게 검증할까 — 드리프트 창(window)

휴대폰 시계와 서버 시계가 몇 초 어긋나거나, 사용자가 코드를 늦게 입력할 수 있다. 그래서 서버는 현재 시간 단계 하나만 보지 않고 앞뒤로 ±1단계(±30초)까지 계산해 하나라도 맞으면 통과시킨다.

창을 넓힐수록 시계 오차에 관대하지만, 공격자가 코드를 추측·재사용할 시간도 늘어난다. 실무에서는 ±1단계가 표준이고, 한 번 쓴 코드는 서버가 기록해 재사용을 막는다(replay 방지).

5. HOTP vs TOTP

HOTP (RFC 4226)TOTP (RFC 6238)
카운터 재료사용할 때마다 +1 되는 정수⌊시각/30⌋ — 시간이 자동으로 올림
동기화양쪽 카운터가 어긋나면 재동기 필요시계만 맞으면 됨 (NTP)
코드 수명다음에 쓸 때까지 무한30초
대표 사용처하드웨어 토큰(YubiKey OTP 등)Google/MS Authenticator, Authy

TOTP는 사실 HOTP의 카운터에 시간을 넣은 것이다. 절단·6자리 추출 로직은 완전히 동일하다.

6. 남는 약점