PHP Integrated Dynamic password Authentication (recommended)

Source: Internet
Author: User
Tags ord php framework rfc sha1 sha1 hash sprintf
This article is mainly for everyone to introduce the PHP integrated Dynamic password Authentication, dynamic password using a secret, using the password to invalidate the way to improve security performance, interested in small partners can refer to

Most systems are currently using a static password for authentication login, but because the static password is easy to be stolen, its security can not meet the security requirements.

Dynamic password is used once a secret, use the password to invalidate the way to prevent password theft security issues.
The dynamic password is divided into HOTP (dynamic password based on event count, RFC4226), TOTP (dynamic password based on time count, RFC6238), OCRA (Challenge Response dynamic password, RFC6287) and so on.

This paper introduces the scheme of dynamic password Authentication with integrated TOTP mode, the PHP framework uses Thinkphp3.2.3, and the dynamic password generator uses Google authtication.

1. Add oath algorithm class for thinkphp framework

The oath algorithm encapsulates the class oath.php code as follows:

<? php/** * This program was free software:you can redistribute it and/or modify * it under the terms of the GNU General publ IC License as published by * The free software Foundation, either version 3 of the License, or * (at your option) any late R version. * * This program was distributed in the hope that it'll be useful, * but without any WARRANTY; Without even the implied warranty of * merchantability or FITNESS for A particular PURPOSE. See the * GNU general public License for more details. * * You should has received a copy of the GNU general public License * along. If not, see 

Because the BASE32 encoding is used for the seed key in Google's dynamic password algorithm, the BASE32 algorithm is required, and the base32.php content is as follows:

<?php//namespace base32;/** * BASE32 encoder and Decoder * * Last update:2012-06-20 * * RFC 4648 compliant * @link HTT P://www.ietf.org/rfc/rfc4648.txt * * Some groundwork based on this class * HTTPS://GITHUB.COM/NTICOMPASS/PHP-BASE32 * @a Uthor Christian Riesen <chris.riesen@gmail.com> * @link http://christianriesen.com * @license MIT license See Licens E file */class base32{/** * Alphabet for encoding and decoding BASE32 * * @var array */private static $alphabet = ' A Bcdefghijklmnopqrstuvwxyz234567= '; /** * Creates an array from a binary string into a given chunk size * * @param string $binaryString string to chunk *  @param integer $bits number of bits per chunk * @return Array */private static function chunk ($binaryString, $bits) {  $binaryString = Chunk_split ($binaryString, $bits, '); if (substr ($binaryString, (strlen ($binaryString))-1) = = ") {$binaryString = substr ($binaryString, 0, strlen ($binary  String)-1); } Return Explode (", $binaryString); }/** * encodes into BASE32 * * @param string $string Clear text String * @return string BASE32 encoded String */Publi  C static function encode ($string) {if (strlen ($string) = = 0) {//Gives an empty string return ';  }//Convert string to binary $binaryString = '; foreach (Str_split ($string) as $s) {//Return each character as a 8-bit binary string $binaryString. = sprintf ('%08b  ', Ord ($s));  }//Break to 5-bit chunks, then break that to an array $binaryArray = Self::chunk ($binaryString, 5);  Pad array to is pisible by 8 while (count ($binaryArray)% 8!== 0) {$binaryArray [] = null;  } $base 32String = ';   Encode in Base32 foreach ($binaryArray as $bin) {$char = 32;    if (!is_null ($bin)) {//Pad the binary strings $bin = Str_pad ($bin, 5, 0, str_pad_right);   $char = Bindec ($bin);  }//Base32 character $base 32String. = self:: $alphabet [$char]; } return $base 32String; }/** * Decodes base32 * * @param string $base 32String Base32 Encoded String * @return string Clear text string */public static function decode ($base 32String)  per cases $base 32String = Strtoupper ($base 32String);  Remove anything. is not base32 alphabet $pattern = '/[^a-z2-7]/';  $base 32String = preg_replace ($pattern, ", $base 32String);  if (strlen ($base 32String) = = 0) {//Gives an empty string return ';  } $base 32Array = Str_split ($base 32String);  $string = ";   foreach ($base 32Array as $str) {$char = Strpos (self:: $alphabet, $STR);   Ignore the padding character if ($char!==) {$string. = sprintf ('%05b ', $char);  }} while (Strlen ($string)%8!== 0) {$string = substr ($string, 0, strlen ($string)-1);  } $binaryArray = Self::chunk ($string, 8);  $realString = ";   foreach ($binaryArray as $bin) {//Pad each value to 8 bits $bin = Str_pad ($bin, 8, 0, str_pad_right);  Convert binary strings to ASCII $realString. = Chr (Bindec ($bin)); } return $realString; }}?>

Put these two files into the Thinkphp\library\vendor\oath directory of the thinkphp framework, and the oath directory is created by itself.

2. Add Database Fields

The user table adds the following fields:
Auth_type (0-static password, 1-dynamic password)
Seed (seeds key)
Temp_seed (temporary seed key)
Last_logintime (Last Login success time)
LAST_OTP (last password used)
Where Auth_type is to indicate which authentication method the user uses, seed is the user's seed key, temp_seed a seed key that is temporarily saved before the user is opened, and if the user opens the dynamic password authentication succeeds, the field content will be filled into the seed field. Last_logintime and LAST_OTP are the time and dynamic passwords for the last successful authentication and are used to prevent users from reusing the same password.

3. Code Integration

1), open the dynamic password

In the original system Change Password page, plus the choice of authentication method, for example:

If the user chooses the dynamic password method, a QR code will be generated for the user to open the dynamic password. In order to be compatible with Google Authtication, the QR code format is the same as Google. The method of generating two-dimensional code see my other article, "Thinkphp3.2.3 integration Phpqrcode Create a QR code with logo."
Generate the key QR code as follows:

Public Function QRCode () {   Vendor (' oath.base32 ');  $base = new \base32 ();  $rand = random (16);//Generate stochastic seed  $rand = $base 32->encode ($rand);  $rand =str_replace (' = ', ' ', $rand);//Remove filled ' = '  $errorCorrectionLevel =intval (3);//fault-tolerant level   $matrixPointSize = Intval (8);//Generate picture size  //Generate two-dimensional code picture   Vendor (' Phpqrcode.phpqrcode ');  $object = new \qrcode ();  $text = sprintf ("otpauth://totp/%s?secret=%s", $user, $rand);  $object->png ($text, False, $errorCorrectionLevel, $matrixPointSize, 2);  The generated seed $rand is saved to the Temp_seed field in the database}

The random string function is generated. $rand =str_replace (' = ', ', $rand) This code is because the BASE32 decoding algorithm in the Google phone token is not populated with the ' = ' number.

The code to verify the user's dynamic password is as follows:

Read Temp_seedvendor (' Oath.oath ') from the database, $object = new \google2fa (), if ($object->verify_key ($temp _seed, $OTP)) {validation succeeded, Update the database seed to Temp_seed,auth_type to 1,LAST_OTP for OTP}

2), dynamic password login

Code for user Dynamic password logon verification:

Reads the AUTH_TYPE,SEED,LAST_OTP field from the database.

if ($auth _type==1) {//Dynamic password//Prevent duplicate Authentication     if ($lat _OTP = = $OTP) {  Dynamic password re-use return     } Vendor (' Oath.oath '); $object = new \ GOOGLE2FA (); if (! $object->verify_key ($seed, $OTP)) {  dynamic password is incorrect} else {  login succeeded, LAST_OTP database updated to $otp,last_logintime to time ()}    }

4. Test verification

Download Google authtication, log in to the system with a static password and go to the Change Password page.
Open Google authtication, scan QR code, will show the dynamic password.

Save content, activate dynamic password successfully!
Then you can log into the system with the dynamic password on the tall!

Summary: The above is the entire content of this article, I hope to be able to help you learn.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.