One Time Password의 약자로, 우리말로 하면 일회용 비밀번호라 할 수 있다.
일회성이라는 특징 때문에 일반 비밀번호 입력이나 공인인증서 이용보다도 더 안전한 방법으로 알려져있다.
주로 금융권이나 일반 웹사이트 2차 로그인 인증으로 많이 활용되고 있다.
OTP 인증은 OTP 기기와 서버가 통신하는것이 아니라 같은 알고리즘을 이용하여 알고리즘을 통해 확인하는 방식이라고 한다.
여기서 말한 OTP 기기란 스마트폰에 있는 Google Authenticator라는 앱으로 대체한다는 것이다.
<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;
}