From 18f8e04423dfe377ac53a8b27bb717944ce411dc Mon Sep 17 00:00:00 2001 From: paulr Date: Thu, 18 Nov 2010 09:04:32 +1100 Subject: [PATCH] renamed the main library --- lib/ga4php.php | 379 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/lib.php | 377 ------------------------------------------------------- 2 files changed, 379 insertions(+), 377 deletions(-) create mode 100644 lib/ga4php.php delete mode 100644 lib/lib.php diff --git a/lib/ga4php.php b/lib/ga4php.php new file mode 100644 index 0000000..8bc5946 --- /dev/null +++ b/lib/ga4php.php @@ -0,0 +1,379 @@ +getData($username); + $deco = unserialize(base64_decode($data)); + + if(!$deco) { + $deco = $this->createEmptyData(); + } + + return $deco; + } + + + function internalPutData($username, $data) { + $enco = base64_encode(serialize($data)); + + return $this->putData($username, $enco); + } + + + // set the token type the user it going to use. + // this defaults to HOTP - we only do 30s token + // so lets not be able to set that yet + function setTokenType($username, $tokentype) { + $tokentype = strtoupper($tokentype); + if($tokentype!="HOTP" and $tokentype!="TOTP") { + $errorText = "Invalid Token Type"; + return false; + } + + $data = $this->internalGetData($username); + $data["tokentype"] = $tokentype; + $this->internalPutData($username, $data); + + return true; + } + + + // create "user" with insert + function setUser($username, $ttype="HOTP", $key = "", $hexkey="") { + if($key == "") $key = $this->createBase32Key(); + $hkey = $this->helperb322hex($key); + if($hexkey != "") $hkey = $hexkey; + + $token = $this->internalGetData($username); + $token["tokenkey"] = $hkey; + $token["tokentype"] = $ttype; + + $this->internalPutData($username, $token); + return $key; + } + + + function hasToken($username) { + $token = $this->internalGetData($username); + // TODO: change this to a pattern match for an actual key + if(!isset($token["tokenkey"])) return false; + if($token["tokenkey"] == "") return false; + return true; + } + + + // sets the key for a user - this is assuming you dont want + // to use one created by the application. returns false + // if the key is invalid or the user doesn't exist. + function setUserKey($username, $key) { + // consider scrapping this + $token = $this->internalGetData($username); + $token["tokenkey"] = $key; + $this->internalPutData($username, $token); + } + + + // self explanitory? + function deleteUser($username) { + // oh, we need to figure out how to do thi? + $data = $this->internalGetData($username); + $data["tokenkey"] = ""; + $this->internalPutData($username); + } + + // user has input their user name and some code, authenticate + // it + function authenticateUser($username, $code) { + + if(preg_match("/[0-9][0-9][0-9][0-9][0-9][0-9]/",$code)<1) return false; + error_log("begin auth user"); + $tokendata = $this->internalGetData($username); + $asdf = print_r($tokendata, true); + error_log("dat is $asdf"); + + if($tokendata["tokenkey"] == "") { + $errorText = "No Assigned Token"; + return false; + } + + // TODO: check return value + $ttype = $tokendata["tokentype"]; + $tlid = $tokendata["tokencounter"]; + $tkey = $tokendata["tokenkey"]; + + $asdf = print_r($tokendata, true); + error_log("dat is $asdf"); + switch($ttype) { + case "HOTP": + error_log("in hotp"); + $st = $tlid; + $en = $tlid+20; + for($i=$st; $i<$en; $i++) { + $stest = $this->oath_hotp($tkey, $i); + error_log("testing code: $code, $stest, $tkey, $tid"); + if($code == $stest) { + $tokendata["tokencounter"] = $i; + $this->internalPutData($username, $tokendata); + return true; + } + } + return false; + break; + case "TOTP": + error_log("in totp"); + $t_now = time(); + $t_ear = $t_now - 45; + $t_lat = $t_now + 60; + $t_st = ((int)($t_ear/30)); + $t_en = ((int)($t_lat/30)); + //error_log("kmac: $t_now, $t_ear, $t_lat, $t_st, $t_en"); + for($i=$t_st; $i<=$t_en; $i++) { + $stest = $this->oath_hotp($tkey, $i); + error_log("testing code: $code, $stest, $tkey\n"); + if($code == $stest) { + return true; + } + } + break; + default: + echo "how the frig did i end up here?"; + } + + return false; + + } + + // this function allows a user to resync their key. If too + // many codes are called, we only check up to 20 codes in the future + // so if the user is at 21, they'll always fail. + function resyncCode($username, $code1, $code2) { + // here we'll go from 0 all the way thru to 200k.. if we cant find the code, so be it, they'll need a new one + // for HOTP tokens we start at x and go to x+20 + + // for TOTP we go +/-1min TODO = remember that +/- 1min should + // be changed based on stepping if we change the expiration time + // for keys + + // $this->dbConnector->query('CREATE TABLE "tokens" ("token_id" INTEGER PRIMARY KEY AUTOINCREMENT,"token_key" TEXT NOT NULL, "token_type" TEXT NOT NULL, "token_lastid" INTEGER NOT NULL)'); + $tokendata = internalGetData($username); + + // TODO: check return value + $ttype = $tokendata["tokentype"]; + $tlid = $tokendata["tokencounter"]; + $tkey = $tokendata["tokenkey"]; + + if($tkey == "") { + $this->errorText = "No Assigned Token"; + return false; + } + + switch($ttype) { + case "HOTP": + $st = 0; + $en = 200000; + for($i=$st; $i<$en; $i++) { + $stest = $this->oath_hotp($tkey, $i); + //echo "code: $code, $stest, $tkey\n"; + if($code1 == $stest) { + $stest2 = $this->oath_hotp($tkey, $i+1); + if($code2 == $stest2) { + $tokendata["tokencounter"] = $i+1; + internalPutData($username, $tokendata); + return true; + } + } + } + return false; + break; + case "TOTP": + break; + default: + echo "how the frig did i end up here?"; + } + + return false; + } + + // gets the error text associated with the last error + function getErrorText() { + return $this->errorText; + } + + // create a url compatibile with google authenticator. + function createURL($user) { + // oddity in the google authenticator... hotp needs to be lowercase. + $data = $this->internalGetData($user); + $toktype = $data["tokentype"]; + $key = $this->helperhex2b32($data["tokenkey"]); + $toktype = strtolower($toktype); + if($toktype == "hotp") { + $url = "otpauth://$toktype/$user?secret=$key&counter=1"; + } else { + $url = "otpauth://$toktype/$user?secret=$key"; + } + //echo "url: $url\n"; + return $url; + } + + // creeates a base 32 key (random) + function createBase32Key() { + $alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; + $key = ""; + for($i=0; $i<16; $i++) { + $offset = rand(0,strlen($alphabet)-1); + //echo "$i off is $offset\n"; + $key .= $alphabet[$offset]; + } + + return $key; + } + + // returns a hex key + function getKey($username) { + $data = $this->internalGetData($username); + $key = $data["tokenkey"]; + + return $key; + } + + // get key type + function getTokenType($username) { + $data = $this->internalGetData($username); + $toktype = $data["tokentype"]; + + return $toktype; + } + + + function helperb322hex($b32) { + $alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; + + $out = ""; + $dous = ""; + + for($i = 0; $i < strlen($b32); $i++) { + $in = strrpos($alphabet, $b32[$i]); + $b = str_pad(base_convert($in, 10, 2), 5, "0", STR_PAD_LEFT); + $out .= $b; + $dous .= $b."."; + } + + $ar = str_split($out,20); + + //echo "$dous, $b\n"; + + //print_r($ar); + $out2 = ""; + foreach($ar as $val) { + $rv = str_pad(base_convert($val, 2, 16), 5, "0", STR_PAD_LEFT); + //echo "rv: $rv from $val\n"; + $out2 .= $rv; + + } + //echo "$out2\n"; + + return $out2; + } + + function helperhex2b32($hex) { + $alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; + + $ar = str_split($hex, 5); + + $out = ""; + foreach($ar as $var) { + $bc = base_convert($var, 16, 2); + $bin = str_pad($bc, 20, "0", STR_PAD_LEFT); + $out .= $bin; + //echo "$bc was, $var is, $bin are\n"; + } + + $out2 = ""; + $ar2 = str_split($out, 5); + foreach($ar2 as $var2) { + $bc = base_convert($var2, 2, 10); + $out2 .= $alphabet[$bc]; + } + + return $out2; + } + + function oath_hotp($key, $counter) + { + $key = pack("H*", $key); + $cur_counter = array(0,0,0,0,0,0,0,0); + for($i=7;$i>=0;$i--) + { + $cur_counter[$i] = pack ('C*', $counter); + $counter = $counter >> 8; + } + $bin_counter = implode($cur_counter); + // Pad to 8 chars + if (strlen ($bin_counter) < 8) + { + $bin_counter = str_repeat (chr(0), 8 - strlen ($bin_counter)) . $bin_counter; + } + + // HMAC + $hash = hash_hmac ('sha1', $bin_counter, $key); + return str_pad($this->oath_truncate($hash), 6, "0", STR_PAD_LEFT); + } + + function oath_truncate($hash, $length = 6) + { + // Convert to dec + foreach(str_split($hash,2) as $hex) + { + $hmac_result[]=hexdec($hex); + } + + // Find offset + $offset = $hmac_result[19] & 0xf; + + // Algorithm from RFC + return + ( + (($hmac_result[$offset+0] & 0x7f) << 24 ) | + (($hmac_result[$offset+1] & 0xff) << 16 ) | + (($hmac_result[$offset+2] & 0xff) << 8 ) | + ($hmac_result[$offset+3] & 0xff) + ) % pow(10,$length); + } + + + // some private data bits. + private $getDatafunction; + private $putDatafunction; + private $errorText; + private $errorCode; + + /* + * error codes + * 1: Auth Failed + * 2: No Key + * 3: input code was invalid (user input an invalid code - must be 6 numerical digits) + * 4: user doesnt exist? + * 5: key invalid + */ +} +?> diff --git a/lib/lib.php b/lib/lib.php deleted file mode 100644 index 558e215..0000000 --- a/lib/lib.php +++ /dev/null @@ -1,377 +0,0 @@ -getData($username); - $deco = unserialize(base64_decode($data)); - - if(!$deco) { - $deco = $this->createEmptyData(); - } - - return $deco; - } - - - function internalPutData($username, $data) { - $enco = base64_encode(serialize($data)); - - return $this->putData($username, $enco); - } - - - // set the token type the user it going to use. - // this defaults to HOTP - we only do 30s token - // so lets not be able to set that yet - function setupTokenType($username, $tokentype) { - if($tokentype!="HOTP" and $tokentype!="TOTP") { - $errorText = "Invalid Token Type"; - return false; - } - - $data = $this->internalGetData($username); - $data["tokentype"] = $tokentype; - $this->internalPutData($username, $data); - - return true; - } - - - // create "user" with insert - function setUser($username, $ttype="HOTP", $key = "") { - if($key == "") $key = $this->createBase32Key(); - $hkey = $this->helperb322hex($key); - - $token = $this->internalGetData($username); - $token["tokenkey"] = $hkey; - $token["tokentype"] = $ttype; - - $this->internalPutData($username, $token); - return $key; - } - - - function hasToken($username) { - $token = $this->internalGetData($username); - // TODO: change this to a pattern match for an actual key - if(!isset($token["tokenkey"])) return false; - if($token["tokenkey"] == "") return false; - return true; - } - - - // sets the key for a user - this is assuming you dont want - // to use one created by the application. returns false - // if the key is invalid or the user doesn't exist. - function setUserKey($username, $key) { - // consider scrapping this - $token = $this->internalGetData($username); - $token["tokenkey"] = $key; - $this->internalPutData($username, $token); - } - - - // self explanitory? - function deleteUser($username) { - // oh, we need to figure out how to do thi? - $data = $this->internalGetData($username); - $data["tokenkey"] = ""; - $this->internalPutData($username); - } - - // user has input their user name and some code, authenticate - // it - function authenticateUser($username, $code) { - - if(preg_match("/[0-9][0-9][0-9][0-9][0-9][0-9]/",$code)<1) return false; - error_log("begin auth user"); - $tokendata = $this->internalGetData($username); - $asdf = print_r($tokendata, true); - error_log("dat is $asdf"); - - if($tokendata["tokenkey"] == "") { - $errorText = "No Assigned Token"; - return false; - } - - // TODO: check return value - $ttype = $tokendata["tokentype"]; - $tlid = $tokendata["tokencounter"]; - $tkey = $tokendata["tokenkey"]; - - $asdf = print_r($tokendata, true); - error_log("dat is $asdf"); - switch($ttype) { - case "HOTP": - error_log("in hotp"); - $st = $tlid; - $en = $tlid+20; - for($i=$st; $i<$en; $i++) { - $stest = $this->oath_hotp($tkey, $i); - error_log("testing code: $code, $stest, $tkey, $tid"); - if($code == $stest) { - $tokendata["tokencounter"] = $i; - $this->internalPutData($username, $tokendata); - return true; - } - } - return false; - break; - case "TOTP": - error_log("in totp"); - $t_now = time(); - $t_ear = $t_now - 45; - $t_lat = $t_now + 60; - $t_st = ((int)($t_ear/30)); - $t_en = ((int)($t_lat/30)); - //error_log("kmac: $t_now, $t_ear, $t_lat, $t_st, $t_en"); - for($i=$t_st; $i<=$t_en; $i++) { - $stest = $this->oath_hotp($tkey, $i); - error_log("testing code: $code, $stest, $tkey\n"); - if($code == $stest) { - return true; - } - } - break; - default: - echo "how the frig did i end up here?"; - } - - return false; - - } - - // this function allows a user to resync their key. If too - // many codes are called, we only check up to 20 codes in the future - // so if the user is at 21, they'll always fail. - function resyncCode($username, $code1, $code2) { - // here we'll go from 0 all the way thru to 200k.. if we cant find the code, so be it, they'll need a new one - // for HOTP tokens we start at x and go to x+20 - - // for TOTP we go +/-1min TODO = remember that +/- 1min should - // be changed based on stepping if we change the expiration time - // for keys - - // $this->dbConnector->query('CREATE TABLE "tokens" ("token_id" INTEGER PRIMARY KEY AUTOINCREMENT,"token_key" TEXT NOT NULL, "token_type" TEXT NOT NULL, "token_lastid" INTEGER NOT NULL)'); - $tokendata = internalGetData($username); - - // TODO: check return value - $ttype = $tokendata["tokentype"]; - $tlid = $tokendata["tokencounter"]; - $tkey = $tokendata["tokenkey"]; - - if($tkey == "") { - $this->errorText = "No Assigned Token"; - return false; - } - - switch($ttype) { - case "HOTP": - $st = 0; - $en = 200000; - for($i=$st; $i<$en; $i++) { - $stest = $this->oath_hotp($tkey, $i); - //echo "code: $code, $stest, $tkey\n"; - if($code1 == $stest) { - $stest2 = $this->oath_hotp($tkey, $i+1); - if($code2 == $stest2) { - $tokendata["tokencounter"] = $i+1; - internalPutData($username, $tokendata); - return true; - } - } - } - return false; - break; - case "TOTP": - break; - default: - echo "how the frig did i end up here?"; - } - - return false; - } - - // gets the error text associated with the last error - function getErrorText() { - return $this->errorText; - } - - // create a url compatibile with google authenticator. - function createURL($user) { - // oddity in the google authenticator... hotp needs to be lowercase. - $data = $this->internalGetData($user); - $toktype = $data["tokentype"]; - $key = $this->helperhex2b32($data["tokenkey"]); - $toktype = strtolower($toktype); - if($toktype == "hotp") { - $url = "otpauth://$toktype/$user?secret=$key&counter=1"; - } else { - $url = "otpauth://$toktype/$user?secret=$key"; - } - //echo "url: $url\n"; - return $url; - } - - // creeates a base 32 key (random) - function createBase32Key() { - $alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; - $key = ""; - for($i=0; $i<16; $i++) { - $offset = rand(0,strlen($alphabet)-1); - //echo "$i off is $offset\n"; - $key .= $alphabet[$offset]; - } - - return $key; - } - - // returns a hex key - function getKey($username) { - $data = $this->internalGetData($username); - $key = $data["tokenkey"]; - - return $key; - } - - // get key type - function getTokenType($username) { - $data = $this->internalGetData($username); - $toktype = $data["tokentype"]; - - return $toktype; - } - - - function helperb322hex($b32) { - $alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; - - $out = ""; - $dous = ""; - - for($i = 0; $i < strlen($b32); $i++) { - $in = strrpos($alphabet, $b32[$i]); - $b = str_pad(base_convert($in, 10, 2), 5, "0", STR_PAD_LEFT); - $out .= $b; - $dous .= $b."."; - } - - $ar = str_split($out,20); - - //echo "$dous, $b\n"; - - //print_r($ar); - $out2 = ""; - foreach($ar as $val) { - $rv = str_pad(base_convert($val, 2, 16), 5, "0", STR_PAD_LEFT); - //echo "rv: $rv from $val\n"; - $out2 .= $rv; - - } - //echo "$out2\n"; - - return $out2; - } - - function helperhex2b32($hex) { - $alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; - - $ar = str_split($hex, 5); - - $out = ""; - foreach($ar as $var) { - $bc = base_convert($var, 16, 2); - $bin = str_pad($bc, 20, "0", STR_PAD_LEFT); - $out .= $bin; - //echo "$bc was, $var is, $bin are\n"; - } - - $out2 = ""; - $ar2 = str_split($out, 5); - foreach($ar2 as $var2) { - $bc = base_convert($var2, 2, 10); - $out2 .= $alphabet[$bc]; - } - - return $out2; - } - - function oath_hotp($key, $counter) - { - $key = pack("H*", $key); - $cur_counter = array(0,0,0,0,0,0,0,0); - for($i=7;$i>=0;$i--) - { - $cur_counter[$i] = pack ('C*', $counter); - $counter = $counter >> 8; - } - $bin_counter = implode($cur_counter); - // Pad to 8 chars - if (strlen ($bin_counter) < 8) - { - $bin_counter = str_repeat (chr(0), 8 - strlen ($bin_counter)) . $bin_counter; - } - - // HMAC - $hash = hash_hmac ('sha1', $bin_counter, $key); - return str_pad($this->oath_truncate($hash), 6, "0", STR_PAD_LEFT); - } - - function oath_truncate($hash, $length = 6) - { - // Convert to dec - foreach(str_split($hash,2) as $hex) - { - $hmac_result[]=hexdec($hex); - } - - // Find offset - $offset = $hmac_result[19] & 0xf; - - // Algorithm from RFC - return - ( - (($hmac_result[$offset+0] & 0x7f) << 24 ) | - (($hmac_result[$offset+1] & 0xff) << 16 ) | - (($hmac_result[$offset+2] & 0xff) << 8 ) | - ($hmac_result[$offset+3] & 0xff) - ) % pow(10,$length); - } - - - // some private data bits. - private $getDatafunction; - private $putDatafunction; - private $errorText; - private $errorCode; - - /* - * error codes - * 1: Auth Failed - * 2: No Key - * 3: input code was invalid (user input an invalid code - must be 6 numerical digits) - * 4: user doesnt exist? - * 5: key invalid - */ -} -?> \ No newline at end of file -- 1.7.0.4