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:
- Step 1: Enter the password of the regular account and enter the second verification page after the verification is successful.
- 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.
- 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:
- 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