How to Develop Two-Step Verification Function

Keywords: Java Google Mobile Database PHP

What is two-step verification?

_Two-step authentication means that when a user logs into an account, besides entering a username and password, the user is required to enter a dynamic password, which adds an extra layer of protection to the account. This dynamic password is either dedicated hardware or provided by the user's mobile phone APP. Even if the intruder steals the user's password, it will be unable to log in to the account because it can't use the user's mobile phone. Many game clients and online banking adopt this approach. Take the bank as an example. When the user carries out the transfer operation, the first step is to input a 6-bit withdrawal password, and the second step is to input the number on the dynamic password, which is the hardware provided by the bank when opening an account.

Principle of Dynamic Cryptography

_Client and server negotiate a key K in advance for the generation of one-time password, which is not known by any third party. In addition, both client and server have a counter C, and the count value is synchronized beforehand. When verifying, the client uses the combination of key and counter (K,C) to calculate the one-time password using the HMAC (Hash-based Message Authentication Code) algorithm. The formula is as follows: HOTP(K,C) = Truncate(HMAC-SHA-1(K,C)) above uses HMAC-SHA-1, of course, HMAC-MD5 can also be used. HMAC algorithm obtains a large number of values, which is not convenient for users to input, so truncate is needed to become a set of not too long decimal numbers (such as 6 bits). Client counter C count value plus 1 after calculation. After the user inputs and submits this set of decimal numbers, the server side calculates the same number and compares it with the value submitted by the user. If the same number is validated, the server side increases the count value C by 1. If not, the validation fails.

operation flow

How to develop this function? Let's clarify its process first:

  1. Step 1: Enter the password of the regular account and enter the second verification page after the verification is successful.
  2. Step 2: The second verification page requires the user to enter the dynamic password. The user's mobile phone must bind the account number through APP before obtaining the dynamic password. APP recommendation eagle2fa.
  3. Step 3: The page generates a two-dimensional code, which is the URI address otpauth://totp/account number? secret = key. After scanning the code with Eagle 2fa, bind the account number, and save the key in the client, as shown in the following figure:
  4. Step 4: Enter the 6-digit number on APP, and verify that it can enter the user center page.
    The most important function is to generate two-dimensional codes and verify dynamic passwords.

Component selection

Google Authenticator is an open source implementation of Google Authenticator

    <dependency>
        <groupId>com.warrenstrange</groupId>
        <artifactId>googleauth</artifactId>
        <version>1.1.2</version>
   </dependency>

zxing Used to Generate Two-Dimensional Code Pictures

    <dependency>
        <groupId>com.google.zxing</groupId>
        <artifactId>javase</artifactId>
        <version>3.3.3</version>
    </dependency>

You can also use WEB API s provided by other websites, such as:

http://qr.liantu.com/api.php?text=x
x Must use UTF8 The encoding format, x Content appears&Symbol time%26 Instead, newline characters are used%0A

critical code

The following code demonstrates how to use the Google Authenticator package:

    private static final GoogleAuthenticator googleAuthenticator = new GoogleAuthenticator();

    /**
     * Because it's just a demonstration, dao doesn't operate on the database, and the real scenario is bound to be persistent
     */
    @Autowired
    private UserDao userDao;

    @PostConstruct
    public void init() {
        googleAuthenticator.setCredentialRepository(new ICredentialRepository() {
            @Override
            public String getSecretKey(String userName) {
                //Search secretKey based on account number
                return userDao.getSecretKey(userName);
            }

            @Override
            public void saveUserCredentials(String userName, String secretKey, int validationCode, List<Integer> scratchCodes) {
                //SecKey should be saved in the database
                userDao.saveUserCredentials(userName, secretKey);
            }
        });
        log.info("GoogleAuthenticator Successful initialization");
    }

The following code is to generate two-dimensional code, uri format can not be written incorrectly.

    // APP must follow this format in order to bind properly
    private static final String KEY_FORMAT = "otpauth://totp/%s?secret=%s";

    /**
     * Generating two-dimensional code links
     */
    private String getQrUrl(String username) {
        //Each call to createCredentials generates a new secretKey
        GoogleAuthenticatorKey key = googleAuthenticator.createCredentials(username);
        log.info("username={},secretKey={}", username, key.getKey());
        return String.format(KEY_FORMAT, username, key.getKey());
    }

The following is the second verification method:

    // Verify dynamic password username account, 6 digits on code app
    public boolean validCode(String username, int code) {
        return googleAuthenticator.authorizeUser(username, code);
    }

Click to get the complete code

Reference (Copyright of some excerpted text belongs to the original author)

https://blog.seetee.me/post/2011/google-two-step-verification/
https://www.zhihu.com/question/20462696/answer/19670601

Posted by jarosciak on Sun, 15 Sep 2019 06:43:04 -0700