에듀테크 프로젝트 대시보드
2단계 인증 (TOTP)
Google Authenticator 앱에 뜨는 6자리 숫자는 어디서 오고, 서버는 그걸 어떻게 검증할까? · RFC 6238
비밀번호는 유출·재사용·피싱에 약하다. 그래서 로그인에 서로 다른 종류의 근거를 두 개 이상 요구한다. 이것이 다중 요소 인증(MFA)이고, 그중 가장 흔한 두 번째 요소가 30초마다 바뀌는 숫자 코드다.
TOTP(Time-based One-Time Password)는 소유 요소를 증명한다. 서버와 앱이 최초 등록 때 비밀 키(secret) 하나를 공유해 두면, 이후에는 네트워크로 그 키를 주고받지 않고도 양쪽이 같은 코드를 독립적으로 계산할 수 있다.
코드를 만드는 재료는 딱 두 가지다.
T = ⌊(현재 유닉스 시각) / 30⌋
이 둘을 HMAC-SHA1에 넣어 20바이트 해시를 얻고, 거기서 동적 절단(Dynamic Truncation)으로
6자리를 뽑는다. 시각이 재료이므로 30초가 지나면 자동으로 다른 코드가 되고, 시간은 흐르기만 하므로
같은 코드는 다시 쓰이지 않는다(one-time).
아래는 브라우저의 Web Crypto API로 실제 RFC 6238 알고리즘을 돌린다. 서버로 아무것도 보내지 않는다.
이 키와 같은 값을 넣은 OTP 앱이라면 세계 어디서든 지금 이 순간 같은 6자리를 표시한다.
마지막 바이트의 하위 4비트 = 오프셋.
그 위치부터 4바이트를 읽어 최상위 비트를 0으로 만든 뒤
% 1,000,000 → 6자리.
휴대폰 시계와 서버 시계가 몇 초 어긋나거나, 사용자가 코드를 늦게 입력할 수 있다. 그래서 서버는 현재 시간 단계 하나만 보지 않고 앞뒤로 ±1단계(±30초)까지 계산해 하나라도 맞으면 통과시킨다.
| HOTP (RFC 4226) | TOTP (RFC 6238) | |
|---|---|---|
| 카운터 재료 | 사용할 때마다 +1 되는 정수 | ⌊시각/30⌋ — 시간이 자동으로 올림 |
| 동기화 | 양쪽 카운터가 어긋나면 재동기 필요 | 시계만 맞으면 됨 (NTP) |
| 코드 수명 | 다음에 쓸 때까지 무한 | 30초 |
| 대표 사용처 | 하드웨어 토큰(YubiKey OTP 등) | Google/MS Authenticator, Authy |
TOTP는 사실 HOTP의 카운터에 시간을 넣은 것이다. 절단·6자리 추출 로직은 완전히 동일하다.