-
OTP 의 원리: Google Authenticator and Authy[+] Security [+]/인증과 암호학 2020. 7. 23. 04:19
OTP(One time Password; 일회성 비밀번호)는 2FA(Two Factor Authentication; 이중 인증)중 하나로서 강력한 보안기법이다.
해커가 어렵게 사용자 계정에 접속해도, OTP가 설정되어있다면 6자리의 숫자를 맞춰야한다.
그 숫자는 주기적으로 변하며, 각각의 계정마다 상이하다.
6자리의 숫자는 무차별 대입 공격이 가능한듯 해 보이지만, 인증 횟수 제한과, 30초 간격으로 변하는 암호는 사실상 브루트 포싱이 불가능하다. (물론 계정을 미리 알고있으면 해킹이 가능하다.)
하지만 Google Authenticator 와 Authy 이 두 모바일 OTP는 서로 바꿔 쓸 수 있다.
즉! Google Authenticator를 쓰고 10분 뒤 Authy를 써도 문제가 없다.
이게 어떻게 가능한 걸까? 안전한가? 원리가 무엇일까?
하는 마음에 직접 뜯어서 파헤쳐보았다.
우선 Google Authenticator 에서 사용하는 암호기법을 살펴보면 TOTP, HOTP 두가지를 사용한다.
개략적으로 포괄하자면 아래의 집합과 같다.
우선 TOTP는 Hash를 기본으로 한다.
Hash는 단방향 알고리즘으로, 복호화하기 어려운 성질덕에 암호화기법으로 널리 이용된다.
해시 : SHA-1 해시 구조
OTP 알고리즘의 동작원리에 대해 기술하려 하였으나, 그 속에 HOTP, TOTP, HMAC, 등등 배경지식을 요구하는 것이 많아 글을 분리하여 작성하도록 하였다. 이 글은 그 첫번째 OTP의 기본이 되는 HASH 알고
devjounal.tistory.com
그 다음으로 HMAC 기법이 이용된다.
HMAC은 Hash-based Message Authentication Code의 줄임말로서,
사용자의 Secret Key를 평문과 조합하여 해시를 발생시키는 방법이다.
HMAC 알고리즘
HMAC(K, text) = H(K xor Opad + H(K xor Ipad + text))
# K는 Secret Key 제 3자가 알지 못하는 비밀 텍스트
# H는 해시함수 MD5 Sha-256 등 다양한 해시 사용가능
# Opad는 Output padding K의 길이 만큼 0x5C 를 반복
# Ipad는 Output padding K의 길이 만큼 0x36 를 반복
Ex)
K = "Hello" => 01001000 01100101 01101100 01101100 01101111 => 0x48656c6c6f
Ipad => 01011100 01011100 01011100 01011100 01011100 => 0x5c5c5c5c5c
1. K xor Ipad => 00010100 00111001 00110000 00110000 00110011 => 0x1439303033
text = "abcde" => 0x6162636465
2. K xor Ipad + text => 0x759b939498
#H는 Sha-1 을 사용하겠습니다.
3. Sha1(K xor Ipad + text) = fe5ce5adc135af4e081618a100a6c7000e350452
4. K xor Opad => 0x48656c6c6f xor 0x3636363636
5. K xor Opad + sha1(K xor Ipad + text) = fe5ce5adc135af4e081618a100a6c77e618f5eab
6. Sha1(K xor Opad + Sha1(K xor Ipad + text)) = 09d5ac5ab199a4956e0528314f54c22beec265dd
Conclusion.
HMAC-SHA-1("Hello", "abcde") = 09d5ac5ab199a4956e0528314f54c22beec265dd
그 다음으로는 HOTP 알고리즘을 거친다.
해쉬값을 짧은 정수로 표현하고자 하는 바람에서 개발되었다.
HOTP 알고리즘은 해쉬 값을 변환하여 정수로만 이루어진 6자리 값을 반환한다.
#정수로만 이루어진 까닭은 기입하기 편하다는 이유때문
HOTP 알고리즘
HOTP(K,text) = Truncate(HMAC-SHA-1(K,text))
# K는 Secret Key 제 3자가 알지 못하는 비밀 텍스트
# Truncate는 동적 stirng 자르기 자세한 내용은 -> 링크
Ex)
HMAC-SHA-1("Hello", "abcde") = 09d5ac5ab199a4956e0528314f54c22beec265dd
1. 8비트 씩 쪼개어 20개의 1바이트 값으로 구분한다.
| Byte Number | => |00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|
| Byte Value | => |09|d5|ac|5a|b1|99|a4|95|6e|05|28|31|4f|54|c2|2b|ee|c2|65|dd|
2.마지막 8비트(0xdd)와 0xf(15) 을 and 연산하고 = > 13(0xd)
그값을 기준으로 우로 4개의 값을 가져온다.
=> Byte Number[13] = 0x54
Byte Number[14] = 0xc2
Byte Number[15] = 0x2b
Byte Number[16] = 0xee
여기서 첫번재 값은(0x54) 맨 앞자리 1비트(MSB)를 제외하여 31비트를 사용한다. => 0x54c22bee
# signed vs unsigned 충돌을 방지하기 위함이라고 한다.
이후 헥사값을 십진법으로 변환하고 => 1422011374
3. 최종적으로 10의 거듭제곱으로 나누어 6자리 숫자를 추출한다. => 1422011374
Conclusion.
HOTP-SHA-1("Hello", "abcde") = 011374
현대의 OTP는 고정된 값을 요구하지 않는다.
가변적이고, 주기적으로 변하는 비밀번호 값을 기입하도록 한다.
시간을 파라미터로 받아 비밀번호를 생성하게끔하는 기법이 TOTP다.
TOTP 알고리즘
TOTP = HOTP(K, T)
HOTP 알고리즘과 아주 흡사하다.
T값을 구하는 것이 TOTP 알고리즘의 전부일 것이다.
T = (UT - T0)/(time step)
우선 UT(UnixTime; UTC of January 1, 1970 이후 경과된 현재시간[단위: 초]) 를 알아야한다.
UT는 서버와 클라이언트가 서로 동기화된다. 이 값에 오차가 생기면 값을 바르게 입력해도 인증에 실패 할 수 있다.
그리고 OTP 갱신 주기를 설정해야 한다.
마지막으로 T0 시스템 파라미터를 알아야한다. OTP가 몇번 갱신 됬는지 그 횟수를 나타낸다. 이 역시 클라이언트와 서버 모두 공유되어야한다.
Ex)
OTP 주기 = 30(sec)
UT = 1595444582.0000
T0 = 12
T = (UT - T0)/30 #소수점 이하 값은 버림.
T = 53181485
위 T값을 이용하여 위에서 진행한 HOTP 알고리즘과 같은 방식으로 계산한다.
TOTP = HOTP("Hello", 53181485)
Acknowledge
docs.python.org/ko/3/library/hmac.html
ko.wikipedia.org/wiki/Google_Authenticator
https://tools.ietf.org/html/rfc6238#ref-UT
'[+] Security [+] > 인증과 암호학' 카테고리의 다른 글
해시 : SHA-1 해시 구조 (0) 2020.07.22