Last active
December 17, 2017 09:05
-
-
Save gkarthikeyanmca/e668db3240452200db95ea91eff17ad3 to your computer and use it in GitHub Desktop.
Blog codes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Google2FA { | |
const keyRegeneration = 30; // Interval between key regeneration | |
const otpLength = 6; // Length of the Token generated | |
private static $lut = array( // Lookup needed for Base32 encoding | |
"A" => 0, "B" => 1, | |
"C" => 2, "D" => 3, | |
"E" => 4, "F" => 5, | |
"G" => 6, "H" => 7, | |
"I" => 8, "J" => 9, | |
"K" => 10, "L" => 11, | |
"M" => 12, "N" => 13, | |
"O" => 14, "P" => 15, | |
"Q" => 16, "R" => 17, | |
"S" => 18, "T" => 19, | |
"U" => 20, "V" => 21, | |
"W" => 22, "X" => 23, | |
"Y" => 24, "Z" => 25, | |
"2" => 26, "3" => 27, | |
"4" => 28, "5" => 29, | |
"6" => 30, "7" => 31 | |
); | |
public static function generate_secret_key($length = 16) { | |
$b32 = "234567QWERTYUIOPASDFGHJKLZXCVBNM"; | |
$s = ""; | |
for ($i = 0; $i < $length; $i++){ | |
$s .= $b32[rand(0,31)]; | |
return $s; | |
} | |
} | |
public static function get_timestamp() { | |
return floor(microtime(true)/self::keyRegeneration); | |
} | |
public static function base32_decode($b32) { | |
$b32 = strtoupper($b32); | |
if (!preg_match('/^[ABCDEFGHIJKLMNOPQRSTUVWXYZ234567]+$/', $b32, $match)) | |
throw new Exception('Invalid characters in the base32 string.'); | |
$l = strlen($b32); | |
$n = 0; | |
$j = 0; | |
$binary = ""; | |
for ($i = 0; $i < $l; $i++) { | |
$n = $n << 5; // Move buffer left by 5 to make room $n = $n + self::$lut[$b32[$i]]; // Add value into buffer $j = $j + 5; // Keep track of number of bits in buffer | |
if ($j >= 8) { | |
$j = $j - 8; | |
$binary .= chr(($n & (0xFF << $j)) >> $j); | |
} | |
} | |
return $binary; | |
} | |
public static function oath_hotp($key, $counter){ | |
if (strlen($key) < 8) | |
throw new Exception('Secret key is too short. Must be at least 16 base 32 characters'); | |
$bin_counter = pack('N*', 0) . pack('N*', $counter); // Counter must be 64-bit int | |
$hash = hash_hmac ('sha1', $bin_counter, $key, true); | |
return str_pad(self::oath_truncate($hash), self::otpLength, '0', STR_PAD_LEFT); | |
} | |
public static function verify_key($b32seed, $key, $window = 4, $useTimeStamp = true) { | |
$timeStamp = self::get_timestamp(); | |
if ($useTimeStamp !== true) $timeStamp = (int)$useTimeStamp; | |
$binarySeed = self::base32_decode($b32seed); | |
for ($ts = $timeStamp - $window; $ts <= $timeStamp + $window; $ts++){ | |
if (self::oath_hotp($binarySeed, $ts) == $key) | |
return true; | |
} | |
return false; | |
} | |
public static function oath_truncate($hash){ | |
$offset = ord($hash[19]) & 0xf; | |
return ( | |
((ord($hash[$offset+0]) & 0x7f) << 24 ) | | |
((ord($hash[$offset+1]) & 0xff) << 16 ) | | |
((ord($hash[$offset+2]) & 0xff) << 8 ) | | |
(ord($hash[$offset+3]) & 0xff) | |
) % pow(10, self::otpLength); | |
} | |
} | |
$InitalizationKey = "coralwebdesigns"; // Set the inital key | |
$TimeStamp = Google2FA::get_timestamp(); | |
$secretkey = Google2FA::base32_decode($InitalizationKey); // Decode it into binary | |
$otp = Google2FA::oath_hotp($secretkey, $TimeStamp); // Get current token | |
echo("Init key: $InitalizationKey\n"); | |
echo("Timestamp: $TimeStamp\n"); | |
echo("One time password: $otp\n"); | |
// Use this to verify a key as it allows for some time drift. | |
$result = Google2FA::verify_key($InitalizationKey, "123456"); | |
var_dump($result); | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment