[JAVA] Google OTP

홍준·2021년 8월 29일
3
post-thumbnail

서론

ISMS 인증심사를 위해 새로운 업무가 추가되었다.
이번에 추가된 업무는 로그인 시 2단계 인증을 추가하는 업무였다.

마침 내가 자주 접속하는 사이트인 GitHub, Aws, Google 등에서 보안을 위해 구글OTP 2차 인증을 이용하고 있었고, 이번 업무에 2단계 인증으로 구글 OTP를 이용한 2단계 인증을 추가해보려고 한다.

OTP란?

One Time Password의 약자로, 우리말로 하면 일회용 비밀번호라 할 수 있다.
일회성이라는 특징 때문에 일반 비밀번호 입력이나 공인인증서 이용보다도 더 안전한 방법으로 알려져있다.
주로 금융권이나 일반 웹사이트 2차 로그인 인증으로 많이 활용되고 있다.


동작원리

구글 OTP를 적용하기 위해 내가 가장 먼저 한 일은 API 문서찾는것이였다. 그런데 아무리
찾아봐도 API 문서 같은게 없어서 당황스러웠다. 다행히 아래의 블로그를 통해 OTP 동작원리를 이해할수 있었다.

참고사이트 : http://zero-gravity.tistory.com/221

OTP 인증은 OTP 기기와 서버가 통신하는것이 아니라 같은 알고리즘을 이용하여 알고리즘을 통해 확인하는 방식이라고 한다.

정리하자면 동작 원리는 아래와 같다.

  • 서버쪽에서 OTP 검증에 사용할 비밀키로 QR 주소를 생성한다.
  • 생성한 QR 주소를 OTP 기기에 입력을한다.
  • 그러면 기기에서는 비밀키 기준으로 하여 30~60초 마다 계속하여 새로운 일회용 비밀번호를 생성해낸다.
  • 그 일회용 비밀번호를 입력하여 서버로 전송하면 서버에서 그 비밀번호가 맞는지 알고리즘으로 확인한다.

여기서 말한 OTP 기기란 스마트폰에 있는 Google Authenticator라는 앱으로 대체한다는 것이다.


OTP 적용해보자

먼저 commons-codec 라이브러리를 추가한다.

       <dependency>
      	   <groupId>commons-codec</groupId>
      	   <artifactId>commons-codec</artifactId>
      	   <version>1.9</version>
       	</dependency>

다음으로 generate 메소드안에서 사용자 비밀키값, QR코드 주소를 생성한다.

 	public HashMap<String, String> generate(String account, String host) { 
		HashMap<String, String> map = new HashMap<String, String>(); 
		byte[] buffer = new byte[5 + 5 * 5]; 
		new Random().nextBytes(buffer); 
		Base32 codec = new Base32(); 
		byte[] secretKey = Arrays.copyOf(buffer, 10); 
		byte[] bEncodedKey = codec.encode(secretKey); 
		String encodedKey = new String(bEncodedKey); 
		String url = getQRBarcodeURL(account, host, encodedKey);
		map.put("encodedKey", encodedKey); 
		map.put("url", url);
		return map; 
	}

생성된 QR코드는 Google Authenticator 앱을 통해 등록한다.
마지막으로 사용자가 입력한 일회용 비밀번호와 사용자의 비밀키값을 checkCode 에서 검증한다.

	public boolean checkCode(String userCode, String otpkey) {
		long otpnum = Integer.parseInt(userCode);
		long wave = new Date().getTime() 
		boolean result = false;
		try {
			Base32 codec = new Base32();
			byte[] decodedKey = codec.decode(otpkey);
			int window = 3;
			for (int i = -window; i <= window; ++i) {
				long hash = verify_code(decodedKey, wave + i);
				if (hash == otpnum) result = true;
			}
		} catch (InvalidKeyException | NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return result;
	}
   

자세한 코드는 내 Github 주소에 정리를 해두었다.


마무리

삽질과 구글링은 꽤나 오래한 것 같은데 정리하려니까 생각 보다 아주 간단하게 구글 OTP 2차인증을 구현할 수 있어서 놀랐다.

한마디로 아주 심플 👍

💡 Tip
만약 휴대폰을 두고 출근 했다면? 크롬 브라우저 확장 프로그램에 구글 OTP 를 등록해서 사용하자.

profile
어제의 나를 이기자 🔥

1개의 댓글

comment-user-thumbnail
2023년 2월 17일

와 너무 쉽게 정리 잘해주셔서 도움이 많이 됐어요! 감사합니다!

답글 달기