개요
요즘 많은 서비스에서 Google Authenticator와 같은 인증 앱으로 OTP 번호를 만들고 입력하면 인증되는 기능을 보셨을겁니다. 이런 인증 방식이 보안에 좋은것 같아서 하이스코어에도 적용해보려고 하는데, 그 전에 어떤 기술인지 공부해 보고자 글을 작성하게 되었습니다.
MFA?
MFA는 Multi-Factor Authentication의 줄임말로, 사용자를 인증할 때 두 가지 이상의 인증 요소를 요구하는 보안 절차입니다. 인증을 여러번 진행하기 때문에, 보안성이 강화된다는 장점이 있습니다.
MFA의 용어를 보면 알겠지만, 로그인 후 이메일로 인증 코드를 보내 인증하는 방법, 별도의 OTP로 생성한 번호를 넣고 인증하는 방법 모두 MFA의 일종입니다. 저는 그중 시간을 기반으로하는 OTP인 TOTP(Time-based One-Time Password)에 대해 알아보려고 합니다.
TOTP?
TOTP는 Time-based One-Time Password의 줄임말로, 뜻 그대로 시간 기반 일회용 비밀번호입니다. TOTP는 서버와 앱이 통신하지 않아도 인증이 가능하다는 장점때문에 현재 많은 서비스에서 MFA 방식으로 채택중인 인증 방법입니다.
동작 원리
TOTP는 앞서 말했듯이 서버와 클라이언트의 통신이 없어도 인증이 가능합니다. 그 이유는 서버와 클라이언트가 같은 Secret Key와 같은 시간을 이용해 OTP 번호를 생성하기 때문에 같은 시점에는 같은 코드를 만들 수 있기 때문입니다. 그 과정에 대해 상세히 알아보겠습니다.
1. 비밀키(Secret Key) 생성 및 공유
TOTP는 서버와 클라이언트가 같은 키를 공유합니다. 주로 서버에서 비밀키를 생성하고, 클라이언트에 전달해서 나눠가지는 방식으로 구현됩니다.
TOTP를 등록할때 웹페이지에 생성된 QRCode를 폰으로 찍으면 인증앱에 등록되는 경험 해보셨을겁니다. 이 과정이 바로 비밀키를 공유하는 과정입니다.
2. OTP 생성
클라이언트는 공유받은 비밀키와 시간을 이용해서 번호를 생성합니다.
시간은 Unix Time을 이용함으로써 서버와 클라이언트가 시간대에 상관없이 같은 시간값을 사용할 수 있도록 합니다. 이때 일정 시간은 같은 값을 유지하기 위해 지정된 시간으로 Unix Time을 나눕니다. 보통은 30초로 설정됩니다.
이렇게 얻은 시간과 비밀키를 HMAC 연산을 통해 해시값을 생성합니다. 마지막으로 생성된 해시값에서 특정 비트를 추출(Truncation)하여 6자리 십진수로 변환합니다. 이렇게 나온 값이 우리가 보는 OTP 번호입니다.
3. 검증
서버에서도 클라이언트와 마찬가지로 동일한 과정을 거쳐 번호를 생성합니다. 사용자가 생성된 번호를 전송하면 서버는 서버에서 생성한 값과 비교해서 일치하는지 확인하고, 일치한다면 인증을 성공시킵니다.
이때 서버와 클라이언트의 시간 오차를 고려해서 앞뒤 30초 간격으로 두 개의 번호를 추가로 생성해서 총 세 개의 번호와 비교해서 하나라도 맞으면 통과시키는 방식으로 구현되기도 합니다.
설명 과정에서 자세히 설명하지 않은 HMAC, Truncation 과정에 대해 자세한 사항이 궁금하다면 RFC 6238 문서에서 확인 가능합니다.
보안 취약점
TOTP는 서버 클라이언트의 통신이 필요가 없다는 점에서 간편하고 좋은 인증 방법이지만, 시크릿키가 유출되면 어느 누구든 OTP를 복제하는게 가능하다는 보안 취약점이 있습니다. 보통 시크릿키를 공유하는 방식으로 QRCdoe를 많이 사용하는데, 사용자가 이점을 인지하지 못하고 공개된 장소에서 잘보이게 둔다거나 캡쳐해둔 사진을 유출한다거나 하면 MFA는 무효화 됩니다. 그래서 해결책으로 제3의 인증앱을 사용하는게 아닌, 자체적인 TOTP 기능을 만들어서 해결하는 회사도 있습니다.
어쩄거나 제가 구현 가능한 MFA중 가장 간편한 방법인것 같습니다. 다음 업데이트 목표중 하나로 TOTP를 도입해 봐야겠습니다.