preface
We tend to use the same password for different websites, so that once the password for one website account is compromised, the security of other accounts using the same password can be compromised. Yes, is the collision library behavior, often your site security mechanism has no problem, but do not stand your user password with other sites used by the removal of the password (now a lot of free social work library, just write a simple violent collision procedures (remember to hang agent), Try out a bunch of valid usernames and passwords), making it easy to bump into the database and find out what usernames and passwords this user has on your site. To get around this, some sites require you to enter another one-time password in addition to your account password when logging in.
And this input one-time password is actually what we call two-step authentication. This is not a novel technology, which has been used in China for many years. For example, the dynamic token used by banks
Again, we have a feeling of things, is the early netease general order (Ye Chun Hui) also used this technology:
It’s not a new technology, but in the early days, due to the low popularity of mobile phones, it was mostly implemented by hardware (once the device ran out of power, it had to be replaced because there was no way to synchronize time with the Internet, but the battery consumption was so low that one could last for several years). But with the popularity of mobile phones, as well as the improvement of people’s safety awareness. More and more sites are being implemented in software (like Evernote, Google, and my team’s site) at a very low cost.
Two-step test principle
Two-factor Authentication (2FA) Two-factor Authentication (2FA) two-factor Authentication (2FA)
OTP
2FA uses One Time Password (OTP), also known as dynamic Password. There are two OTP policies: HMAC-based One Time Password (HOTP) and time-based One Time Password (TOTP). It is the latter time-based dynamic password generation strategy that is widely used at present.
The principle of HOTP
The principle of this section comes from the working principle of two-step authentication of Google accounts
Although TOTP is more commonly used for two-step verification, it is implemented based on HOTP, so let’s first look at how HTOP works.
-
The client and server negotiate a key K in advance for one-time password generation, which is not known to any third party. In addition, the client and server each have a counter, C, and synchronize the count values beforehand.
-
During Authentication, the client uses the Hash-based Message Authentication Code (HMAC) algorithm to calculate the one-time password for the combination of key and counter (K,C), as follows:
HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))
Copy the code
Hmac-sha-1 is used, and HMAC-MD5 can also be used. The HMAC algorithm has a large number of digits, which is inconvenient for users to enter. Therefore, Truncate the value into a group of decimal digits (for example, 6 digits). After the calculation is complete, the client counter C counts and increments by 1.
- After the user inputs and submits this set of decimal numbers, the server performs the same calculation and compares it with the value submitted by the user. If they are the same, the verification passes, and the server increases the count value C by 1. If they are different, the authentication fails.
One of the interesting issues here is that if authentication fails or the client accidentally generates a password one more time, the counter C between the server and client will no longer be synchronized and a Resynchronization mechanism is required. Please refer to RFC 4226 for details.
The principle of TOTP
The principle of this section comes from the working principle of two-step authentication of Google accounts
With HOTP introduced, it’s easy to understand how to use time-based onetime Password (TOTP). TOTP replaces the counter C in HOTP with the current time T, resulting in a one-time password that changes over time. Very interesting!
While the principle is simple, the use of time as a substitute for a counter presents some special and interesting problems, and we’ll explore a few of them.
First of all, what is the value of time T? Because time changes from moment to moment, if you choose a T that changes too quickly (such as the number of seconds from a certain point in time), you won’t have time to enter your password. Choosing a T that changes too slowly (such as the number of hours from a certain point in time) gives a third-party attacker ample time to try all possible one-time passwords (imagine a 6-digit one-time password with only 10^6 combinations), reducing the security of the password. In addition, T changing too slowly can cause another problem. If the user needs to log in to the account twice in a short period of time, the user must wait until the next one-time password is generated because the password is not reusable (this can be configured), which means a maximum of 59 minutes and 59 seconds! This is clearly unacceptable. Given the above considerations, Google chose a time slice of 30 seconds, with the value T being the number of 30 seconds experienced since the Unix epoch (00:00:00, January 1, 1970).
The second problem is that due to network delay, user input delay and other factors, when the server receives the one-time password, the value of T may have changed, so that the one-time password calculated by the server is different from that entered by the user, and the verification fails. One way to solve this problem is for the server to calculate the current time slice and the one-time password value of the preceding N time slices (this can also be configured), as long as one of them is the same as the password entered by the user, the authentication passes. Of course, n should not be too large, otherwise it will reduce security.
TOTP algorithm and features
To sum up, TOTP’s algorithm looks like this:
- The client and server negotiate a SECRET in advance for the one-time password generation process, which is not known to any third party. In addition, both clients and servers use time as a counter.
- For the combination of the key and counter (SECRET,time/30), the client uses the HMAC algorithm to calculate the one-time password. The formula is as follows:
HMAC-SHA-1(SECRET, time/30)
- Various algorithms add special effects to form six digits
Totp-based passwords have the following characteristics
- No memory, no leakage problems like password
- Dynamic generation, every 30 seconds to generate a, greatly improved security
- It has no requirements on the network and can still be used offline
- Low cost, no need to buy hardware and software (just install a client, there are a lot of these on the market)
Two-step verification process implementation
Now that I understand the algorithm and principle, let’s talk about the process:
- The server generates a random code similar to
DPI45HKISEXU6HG7
And save the key in the database. - Display a QR code on the page containing a URI address (
Otpauth :// toTP/vendor: account? Secret = key &issuer= manufacturer
) - The client scans the QR code and puts the key
DPI45HKISEXU6HG7
Save it on the client. - The client uses the key every 30 seconds
DPI45HKISEXU6HG7
And timestamp to generate a 6-digit one-time password through the TOTP algorithm - The user enters this one-time password and the server validates it
Client selection
To implement the above two-step verification process, we need a client (Google Authenticator Compatible App), which we do not need to develop directly, there are many on the market:
- Authy for iOS, Android, Chrome, OS X
- Google Authenticator for iOS
- Google Authenticator for Android
- Google Authenticator (port) on Windows Store
- 1Password for iOS, Android, OS X, Windows
For example, I installed Google Authenticator for iOS, and it looks like this when I open it (because I already use it).
There are two records above, indicating that I have enabled two-step verification on both sites, and then the code will be scanned every 30 seconds according to the TOTP algorithm.
If you want to scan code, directly select the lower right corner of the “+” button, and then choose to scan the TWO-DIMENSIONAL code
Renderings of the process
After having flow chart, cooperate effect chart, understood very well.
- First, when the user selects two-step authentication, he is prompted to bind to Google authenticator immediately
- The front end then asks the server for the binding content of the OTP (
Otpauth :// toTP/vendor: account? Secret = key &issuer= manufacturer
), in the form of two-dimensional code
-
After Google authenticator scans the code, it binds the site’s two-step authentication information (which saves the key, vendor, account number, etc.) and generates the code
-
Finally, input the generated 6-digit code, and then the front end is sent to the server for verification. If the verification passes, then the binding is successful.
-
In this way, when the user logs in next time, the server detects that the user has enabled two-step authentication, so the pop-up box asks the user to enter the OTP code, and then verify. If the verification succeeds, the real product interface is entered
This completes a simple two-step verification process. The client side does not need our own processing, the front end only needs to request the interface, mainly the logic of the server side, responsible for delivering OTP binding content to the client side scan code binding, but also responsible for verification. So let’s talk about what the server side does.
Server processing
We use PHP to handle, and use a third-party packages antonioribeiro/google2fa, the function of this package is very comprehensive, we need to function, and is not only a TOTP verification, he also provides HOTP validation.
Install the package in Composer first:
composer require pragmarx/google2fa
Copy the code
1. Generate secret keys
First make secret key, and then save it in the information table of this user (can’t duplicate with the existing one, if duplicate, create another one).
use PragmaRX\Google2FA\Google2FA;
$google2fa = new Google2FA();
return $google2fa->generateSecretKey();
Copy the code
The default key is 16 bits, which is sufficient, but can be set to 32 bits if more security is required
$secretKey = $google2fa->generateSecretKey(32); // defaults to 16 bytes
Copy the code
2. Generate the OTP binding content of the TWO-DIMENSIONAL code
The next step is to generate the BINDING content of OTP, which is used to display the content of two-dimensional code:
Otpauth :// toTP/vendor: account? Secret = key &issuer= manufacturerCopy the code
There is also an API for this:
$qrCodeUrl = $google2fa->getQRCodeUrl(
$companyName,
$companyEmail,
$secretKey
);
Copy the code
This is generated, but it should be noted that this is only the content after scanning the QR code. It’s just a string, not the QR code itself. If the front end has its own qr code generation program, it just needs to return this to the front end. If the front end does not, then the server can also directly generate a two-dimensional code picture containing the content, and then pass to the front end, the front end directly display this picture.
Note that in the new version of this package, the function of generating TWO-DIMENSIONAL code pictures has been removed. If you want to generate two-dimensional code, you need to combine with other third-party packages, such as Bacon/QRCode to generate:
use PragmaRX\Google2FA\Google2FA;
use BaconQrCode\Renderer\ImageRenderer;
use BaconQrCode\Renderer\Image\ImagickImageBackEnd;
use BaconQrCode\Renderer\RendererStyle\RendererStyle;
use BaconQrCode\Writer;
$google2fa = app(Google2FA::class);
$g2faUrl = $google2fa->getQRCodeUrl(
'pragmarx',
'[email protected]',
$google2fa->generateSecretKey()
);
$writer = new Writer(
new ImageRenderer(
new RendererStyle(400),
new ImagickImageBackEnd()
)
);
$qrcode_image = base64_encode($writer->writeString($g2faUrl));
Copy the code
However, older versions of this package, such as version 4.0.0, do provide this function:
$google2fa->->setAllowInsecureCallToGoogleApis(true);
$google2fa->->getQRCodeGoogleUrl($company, $userEmail, $secret, $size);
Copy the code
Look at his source code, he is directly packaged Google Chart API to deal with:
public function getQRCodeGoogleUrl($company, $holder, $secret, $size = 200) { if (! $this->allowInsecureCallToGoogleApis) { throw new InsecureCallException("It's not secure to send secret keys to Google Apis, you have to explicitly allow it by calling \$google2fa->setAllowInsecureCallToGoogleApis(true)."); } return Url::generateGoogleQRCodeUrl( 'https://chart.googleapis.com/', 'chart', 'chs='.$size.'x'.$size.'&chld=M|0&cht=qr&chl=', $this->getQRCodeUrl($company, $holder, $secret) ); }Copy the code
This is not accessible in China. May also be to consider other reasons, the later version of the new removed this thing.
3. The OTP authentication
After the Google authenticator scans the code, in order to let the server know that there is a scan binding, it needs to enter the OTP for the first time, and then verify it to the server. If the verification succeeds, the process is successful. So there is a verification code involved here, and there is a direct API to deal with that
$secret = $request->input('secret');
$valid = $google2fa->verifyKey($user->google2fa_secret, $secret);
Copy the code
The first parameter is the key generated and stored in the database, and the second parameter is the one-time verification code passed from the front end.
A few notes
Now we have the entire two-step verification process strung together. But there are a few caveats to remember:
1. OTP cannot be multiplexed
The generated OTP cannot be reused. That is, if the OTP on the mobile phone is not refreshed after the user enters THE OTP once during login or dangerous operations, the OTP input is invalid and the user must wait for the OTP refresh on the mobile phone.
Newer software is newer by using the verifyKeyNewer API
$secret = $request->input('secret'); $timestamp = $google2fa->verifyKeyNewer($user->google2fa_secret, $secret, $user->google2fa_ts); if ($timestamp ! == false) { $user->update(['google2fa_ts' => $timestamp]); // successful } else { // failed }Copy the code
2. Set a window period of sufficient time
Since it can be used offline, how can we ensure the time difference? Our server will be compatible with the server time for 30s. In this way, the authentication failure caused by slight time difference is effectively avoided. In addition, the authentication failure is also avoided when the OTP is refreshed after the user enters the OTP and does not submit the OTP.
The API of this package is also available, which can set the window period of validation time. The default is to extend the window period by 1, that is, the validity time of this OTP is 60s:
protected $window = 1; // Keys will be valid for 60 seconds
Copy the code
Of course we can also display the Settings:
$window = 8; // 8 keys (respectively 4 minutes) past and future
$valid = $google2fa->verifyKey($user->google2fa_secret, $secret, $window);
Copy the code
3. Prevent brute force cracking of the OTP
When encountering a brute force OTP that iterates through all 6 digit numbers, we need to limit the number of errors above a certain number.
4. Log in again
After two-step authentication is enabled, all other clients that log in to the client will expire due to two-step authentication and must log in again.
5. During client binding, you can directly enter the key for binding
Sometimes the customer can not scan the TWO-DIMENSIONAL code, at this time we need to provide the key, allowing the client to directly enter the account and key binding, which can also be operated in Google authentication
6. Reserve alternate code behaviors
Sometimes you don’t have Google authenticator installed on your phone, but you need to log in to our site. Therefore, if our site has opened the two-step verification, we will also reserve a set of backup codes. When the authenticator is not around, you can also log in by entering a backup code, but this backup code is also one-time, once used up, can only be refreshed in the background of our product.
conclusion
This is the two-step verification process implemented in project practice. In general, it is not difficult, but be careful because TOTP requires synchronization between the client and the server, and if the client simply sets the time forward, the validation will fail.
Reference Documents:
- How does Google Authenticator work?
- How two-step verification of Google accounts works
- Google Two-Factor Authentication for PHP
- Introduction to Coding two-step authentication technology
- Linux uses Google Authenticator to implement user two-factor authentication
- How does Google Authenticator work?
See my personal site: kebingzao.com/ for more good articles