OTP 개념
- One Time Password의 약자로, 일회용 비밀번호라고 할 수 있다.
- OTP의 종류에는 원리에 따라 S/KEY방식, 시간 동기화 방식, 챌린지 응답 방식, 이벤트 동기화 방식 등이 있다.
- Google Authenticator 앱이 시간 동기화 방식을 사용한다.
TOTP(Time-based One Time Password) 원리
- 시간동기화 방식
OTP를 생성하기 위해 사용하는 입력 값
으로 시각을 사용하는 방식이다.
클라이언트는 현재 시각을 입력값으로 OTP를 생성해 서버로 전송하고, 서버 역시 같은 방식으로 OTP를 생성하여 클라이언트가 전송한 값의 유효성을 검사한다.
어떻게 구현해야할까?
-
OTP 기기(구글 OTP 앱)에서 사용하는 알고리즘을 서버 또는 클라이언트에서 똑같이 구현하면 된다.
-
그럼 유저마다 다 똑같은 일회용 비밀번호를 생성하는 것이 아닌가라는 의문점이 든다.
-
그 기준은 위의 설명의 OTP를 생성하기 위해 사용하는 입력 값
이다.
-
OTP 프로세스는 이와 같다.
- 서버 또는 클라이언트에서 Secret(base32) 키를 생성한다. (유저의 고유 키값)
- 키에 해당하는 QR코드를 생성하면 사용자는 OTP 기기에 등록을 한다.
- 그러면 OTP 기기에서 30초마다 새로운 일회용 비밀번호를 생성한다.
- 그 비밀번호와 서버 또는 클라이언트의 알고리즘 비밀번호가 같은지를 확인하면 된다.
-
코드에서는 어떻게 구현을 해야할까?
- Secret 키 기준으로 새로운 일회용 비밀번호(이하 OTP)를 생성한다.
- 이 때 QR코드도 만들 수 있다.
- QR코드는 단순히 보내준 Secret 키와 계정이름을 담고 있다.
- 이 OTP를 30초마다 재생성한다. (구글 OTP가 30초마다 재생성함)
- QR코드는 변하지 않는다.
- 사용자에게 OTP 번호를 받고 생성되고 있는 OTP 번호와 맞는지 확인
구글 OTP 알고리즘
두번째 사이트의 경우 제이쿼리로 구현한 것이라서 react 버전으로 바꾸어보았다.
구글 OTP(Google Authenticator) 사용법 및 API 연동 방법
Tin Isles
알고리즘은 아래와 같다. 이해하기에는 다소 어려운 부분이 있어서 자세한 설명은 불가능하다.
그래도 큰 맥락정도만 작성하였다.
- SECRET 키를 헥스코드(16진법)로 변경을 한다.
- epoch 타임을 16진수 코드로 변환을 한다.
- 1, 2번의 결과값들을 SHA hashes(안전한 해시 알고리즘)에 등록을 한다.
- 3번값을 이용하여 OTP 번호를 생성한다.
이 알고리즘과 구글 OTP의 구조가 같으므로 동일한 SECRET키를 구글 OTP에 등록하면 동일한 OTP번호가 생성된다. 사용자가 로그인을 하고 2차 인증인 OTP 번호를 입력할 때 서버, 클라이언트에서 SECRET키를 가지고 있다면 비교할 수 있다.
백엔드? 프론트엔드? 누가 구현할 것인가?
react에서 구현 후 생각해 볼 것이 많았다.
누가 SECRET키를 가지고 있을 것인가?
누가 구글OTP 알고리즘을 돌릴 것인가?
- 프론트에서는 SECRET키를 가지고 있을 수가 없다.
- 유저가 하나라면 가능하겠지만 다수의 유저에 대한 정보는 할 수 없다. 보안 ❌
- 그러므로 SECRET키는 서버에서 가지고 있으면 된다.
- 서버에서 받은 SECRET키를 이용하여 유저가 입력한 OTP 코드와 비교하고 서버에게 넘겨준다?
- 즉, 알고리즘을 프론트에서 하겠다?
- 서버 분들과 이야기했을 때 SECRET키의 이동은 비추천. 마치 주민번호가 왔다갔다 하는 느낌?
- 최초등록시에만 SECRET키를 받고 등록시 확인을 위해 넘겨주는 것 정했다.
- 로그인시에는 프론트에서는 OTP 번호만 전달하는 것으로 확정! 땅! 땅! 땅!
결론
프론트에서 하는 것보다 서버에서 하는 것이 낫다.
그래도 이런 프로세스로 진행이 되는구나 라는 개념을 알게되었다.