Two-factor authentication solutions

What is two-factor authentication?

Popular speaking, the general authentication are username / password way, this is only a factor for password authentication, two-factor increase is nothing more than a factor authentication to enhance security.

Common Solutions

  • SMS
  • Mail
  • Phone by voice
  • TOTP Solutions

The first three programs, they were all similar. Server side generated by an algorithm for a random password, delivered to the user via SMS, e-mail or telephone way, random password to the user after Server, Server verified, completed a two-factor authentication as the logon credentials. However, text messages and telephone voice for the operating companies there is a certain cost, in addition to some non-Internet applications may not be through the public network. In this case, TOTP be a good two-factor authentication solutions.

What is TOTP?

It is Time-based One-Time Password shorthand represents a one-time password algorithms based on the timestamp.

If we played Fantasy Westward Journey, then on 将军令should not be unfamiliar, this is a product based on TOTP.

OTP

Before the introduction TOTP, first introducedOTP

One-Time Password shorthand represents a one-time password.

OTP(K,C) = Truncate(HMAC-SHA-1(K,C))

Wherein, K representative of key string; C is a number representing a random number; HMAC-SHA-1 represented by do HMAC SHA-1;

Truncate is a function, for the encrypted string is taken, some of the fields and taking up a string encrypted digital.

Encrypted HMAC-SHA-1 mode is, Truncate to achieve the following:

  • HMAC-SHA-1 to give a length of the encrypted 20-byte encrypted string;
  • Take the last byte of the 20-byte encrypted string, which takes the lower 4 bits of the byte, taken as the standard offset encrypted string;
  • Start offset index according to obtain 4 bytes, big endian (high byte in the low-order address) is composed of an integer embodiment;
  • After intercepts the integer 6 or 8 converted into a string.
 public static String generateOTP(String K,
                                      String C,
                                      String returnDigits,
                                      String crypto){
        int codeDigits = Integer.decode(returnDigits).intValue();
        String result = null;
 
        // K是密码
        // C是产生的随机数
        // crypto是加密算法 HMAC-SHA-1
        byte[] hash = hmac_sha(crypto, K, C);
        // hash为20字节的字符串
 
        // put selected bytes into result int
        // 获取hash最后一个字节的低4位,作为选择结果的开始下标偏移
        int offset = hash[hash.length - 1] & 0xf;
 
        // 获取4个字节组成一个整数,其中第一个字节最高位为符号位,不获取,使用0x7f
        int binary =
                ((hash[offset] & 0x7f) << 24) |
                ((hash[offset + 1] & 0xff) << 16) |
                ((hash[offset + 2] & 0xff) << 8) |
                (hash[offset + 3] & 0xff);
        // 获取这个整数的后6位(可以根据需要取后8位)
        int otp = binary % 1000000;
        // 将数字转成字符串,不够6位前面补0
        result = Integer.toString(otp);
        while (result.length() < codeDigits) {
            result = "0" + result;
        }
        return result;
    }

The results returned is to see a number of dynamic password.

HOTP

We know the basic principles of the OTP, HOTP just one of the parameters C into a random number

Modify the formula

HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))

HOTP: Generates the OTP for the given count

Namely: C as an argument, to obtain dynamic password.

General HOTP predetermined hash function using SHA2, namely: do event based on SHA-256 or SHA-512 [SHA2] synchronization verification hash function;

Detailed TOTP

TOTP just where parameter C into the number generated by the time stamp.

TOTP(K,C) = HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))

TOTP is different from the timestamp calculated C.

C = (T - T0) / X;

T represents the current Unix timestamp

T0 general value to zero.

X represents the number of time steps, that is to say more than a dynamic password is generated for a long time, this time interval is the time X number of steps, the system default is 30 seconds;

E.g:

T0 = ​​0;

X = 30;

T = 30 ~ 59, C = 1; 30 to 59 represents a dynamic password which coincides 30 seconds.

T = 60 ~ 89, C = 2; 30 to 59 represents a dynamic password which coincides 30 seconds.

Different manufacturers use different time steps of;

  • Number of time steps Alibaba treasure identity used is 60 seconds;
  • Number of time steps using the token rather shield is 60 seconds;
  • Google's Authenticator number of time steps is 30 seconds;
  • Token Tencent number of time steps is 60 seconds;

application

There are many clients achieve above have been listed. The server-side implementation library is relatively small, seemingly are also achieved unofficial. Here we recommend a JAVA implementation library , which is a private library, a friend of mind only their own line and the wheel.

Here library based on the realization, some demo code is given for reference purposes only.

package com.github.chenqimiao.util;

import java.text.MessageFormat;

import com.warrenstrange.googleauth.GoogleAuthenticator;
import com.warrenstrange.googleauth.GoogleAuthenticatorConfig;
import com.warrenstrange.googleauth.GoogleAuthenticatorConfig.GoogleAuthenticatorConfigBuilder;
import com.warrenstrange.googleauth.GoogleAuthenticatorKey;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

/**
 * @Auther: chenqimiao
 * @Date: 2019/8/26 22:58
 * @Description: refer https://github.com/wstrange/GoogleAuth
 */
@Slf4j
public class GoogleAuthenticatorUtils {
    // 前缀
    private static final String DEFAULT_USER_PREFIX = "TOTP_USER:";
    // 用户名|密钥|发行者
    public static final String QRCODE_TEMPLATE = "otpauth://totp/" + DEFAULT_USER_PREFIX + "{0}?secret={1}&issuer={2}";
    // 默认的发行者
    public static final String DEFAULT_ISSUER = "DAS_TOTP";

    private static final GoogleAuthenticatorConfig DEFAULT_CONFIG;

    static {
        GoogleAuthenticatorConfigBuilder builder = new GoogleAuthenticatorConfigBuilder();

        // Do something here if you want to set config for GoogleAuthenticator

        DEFAULT_CONFIG = builder.build();
    }


    public static String createQrCodeContent(String username, String secret) {
        return createQrCodeContent(username, secret, DEFAULT_ISSUER);
    }

    public static String createQrCodeContent(String username, String secret, String issuer) {
        return MessageFormat.format(QRCODE_TEMPLATE, username, secret, issuer);
    }

    public static String createSecret() {
        return createSecret(DEFAULT_CONFIG);
    }

    public static String createSecret(GoogleAuthenticatorConfig config) {
        GoogleAuthenticator gAuth = new GoogleAuthenticator(config);
        final GoogleAuthenticatorKey key = gAuth.createCredentials();
        return key.getKey();
    }

    public static boolean verify(Integer totpPwd, String secret) {

        return verify(totpPwd, secret, DEFAULT_CONFIG);
    }

    public static boolean verify(Integer totpPwd, String secret, GoogleAuthenticatorConfig config) {
        GoogleAuthenticator gAuth = new GoogleAuthenticator(config);
        return gAuth.authorize(secret, totpPwd);
    }

    public static Integer getTotpPassword(String secret) {
        return getTotpPassword(secret, DEFAULT_CONFIG);
    }

    public static Integer getTotpPassword(String secret, GoogleAuthenticatorConfig config) {
        GoogleAuthenticator gAuth = new GoogleAuthenticator(config);
        return gAuth.getTotpPassword(secret);
    }

    @SneakyThrows
    public static void main(String args[]) {
        String secret = createSecret();
        String qrcodeContent = createQrCodeContent("chenqimiao", secret);
        System.out.println("qrcodeContent is " + qrcodeContent);

        Integer totpPwd = getTotpPassword(secret);
        System.out.println("Current totp password is " + totpPwd);

        boolean result = verify(totpPwd, secret);
        System.out.println("result is " + result);

    }

qrcodeContent two-dimensional code can be generated by two-dimensional code tool, using the Google Authenticator After scanning the two-dimensional code, it is equivalent to a user bound authenticator.

Guess you like

Origin www.cnblogs.com/think-in-java/p/11443014.html