1
0
mirror of https://git.tt-rss.org/git/tt-rss.git synced 2026-02-10 16:01:33 +00:00

implement one time passwords using TOTP

This commit is contained in:
Andrew Dolgov
2012-09-03 18:33:46 +04:00
parent fd26d5bfdf
commit fb70f26ed9
439 changed files with 11026 additions and 7 deletions

74
lib/otphp/lib/hotp.php Normal file
View File

@@ -0,0 +1,74 @@
<?php
/*
* Copyright (c) 2011 Le Lag
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace OTPHP {
/**
* HOTP - One time password generator
*
* The HOTP class allow for the generation
* and verification of one-time password using
* the HOTP specified algorithm.
*
* This class is meant to be compatible with
* Google Authenticator
*
* This class was originally ported from the rotp
* ruby library available at https://github.com/mdp/rotp
*/
class HOTP extends OTP {
/**
* Get the password for a specific counter value
* @param integer $count the counter which is used to
* seed the hmac hash function.
* @return integer the One Time Password
*/
public function at($count) {
return $this->generateOTP($count);
}
/**
* Verify if a password is valid for a specific counter value
*
* @param integer $otp the one-time password
* @param integer $counter the counter value
* @return bool true if the counter is valid, false otherwise
*/
public function verify($otp, $counter) {
return ($otp == $this->at($counter));
}
/**
* Returns the uri for a specific secret for hotp method.
* Can be encoded as a image for simple configuration in
* Google Authenticator.
*
* @param string $name the name of the account / profile
* @param integer $initial_count the initial counter
* @return string the uri for the hmac secret
*/
public function provisioning_uri($name, $initial_count) {
return "otpauth://hotp/".urlencode($name)."?secret={$this->secret}&counter=$initial_count";
}
}
}

120
lib/otphp/lib/otp.php Normal file
View File

@@ -0,0 +1,120 @@
<?php
/*
* Copyright (c) 2011 Le Lag
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace OTPHP {
/**
* One Time Password Generator
*
* The OTP class allow the generation of one-time
* password that is described in rfc 4xxx.
*
* This is class is meant to be compatible with
* Google Authenticator.
*
* This class was originally ported from the rotp
* ruby library available at https://github.com/mdp/rotp
*/
class OTP {
/**
* The base32 encoded secret key
* @var string
*/
public $secret;
/**
* The algorithm used for the hmac hash function
* @var string
*/
public $digest;
/**
* The number of digits in the one-time password
* @var integer
*/
public $digits;
/**
* Constructor for the OTP class
* @param string $secret the secret key
* @param array $opt options array can contain the
* following keys :
* @param integer digits : the number of digits in the one time password
* Currently Google Authenticator only support 6. Defaults to 6.
* @param string digest : the algorithm used for the hmac hash function
* Google Authenticator only support sha1. Defaults to sha1
*
* @return new OTP class.
*/
public function __construct($secret, $opt = Array()) {
$this->digits = isset($opt['digits']) ? $opt['digits'] : 6;
$this->digest = isset($opt['digest']) ? $opt['digest'] : 'sha1';
$this->secret = $secret;
}
/**
* Generate a one-time password
*
* @param integer $input : number used to seed the hmac hash function.
* This number is usually a counter (HOTP) or calculated based on the current
* timestamp (see TOTP class).
* @return integer the one-time password
*/
public function generateOTP($input) {
$hash = hash_hmac($this->digest, $this->intToBytestring($input), $this->byteSecret());
foreach(str_split($hash, 2) as $hex) { // stupid PHP has bin2hex but no hex2bin WTF
$hmac[] = hexdec($hex);
}
$offset = $hmac[19] & 0xf;
$code = ($hmac[$offset+0] & 0x7F) << 24 |
($hmac[$offset + 1] & 0xFF) << 16 |
($hmac[$offset + 2] & 0xFF) << 8 |
($hmac[$offset + 3] & 0xFF);
return $code % pow(10, $this->digits);
}
/**
* Returns the binary value of the base32 encoded secret
* @access private
* This method should be private but was left public for
* phpunit tests to work.
* @return binary secret key
*/
public function byteSecret() {
return \Base32::decode($this->secret);
}
/**
* Turns an integer in a OATH bytestring
* @param integer $int
* @access private
* @return string bytestring
*/
public function intToBytestring($int) {
$result = Array();
while($int != 0) {
$result[] = chr($int & 0xFF);
$int >>= 8;
}
return str_pad(join(array_reverse($result)), 8, "\000", STR_PAD_LEFT);
}
}
}

27
lib/otphp/lib/otphp.php Normal file
View File

@@ -0,0 +1,27 @@
<?php
/*
* Copyright (c) 2011 Le Lag
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
require_once dirname(__FILE__).'/../vendor/libs.php';
require_once dirname(__FILE__).'/otp.php';
require_once dirname(__FILE__).'/hotp.php';
require_once dirname(__FILE__).'/totp.php';

106
lib/otphp/lib/totp.php Normal file
View File

@@ -0,0 +1,106 @@
<?php
/*
* Copyright (c) 2011 Le Lag
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace OTPHP {
/**
* TOTP - One time password generator
*
* The TOTP class allow for the generation
* and verification of one-time password using
* the TOTP specified algorithm.
*
* This class is meant to be compatible with
* Google Authenticator
*
* This class was originally ported from the rotp
* ruby library available at https://github.com/mdp/rotp
*/
class TOTP extends OTP {
/**
* The interval in seconds for a one-time password timeframe
* Defaults to 30
* @var integer
*/
public $interval;
public function __construct($s, $opt = Array()) {
$this->interval = isset($opt['interval']) ? $opt['interval'] : 30;
parent::__construct($s, $opt);
}
/**
* Get the password for a specific timestamp value
*
* @param integer $timestamp the timestamp which is timecoded and
* used to seed the hmac hash function.
* @return integer the One Time Password
*/
public function at($timestamp) {
return $this->generateOTP($this->timecode($timestamp));
}
/**
* Get the password for the current timestamp value
*
* @return integer the current One Time Password
*/
public function now() {
return $this->generateOTP($this->timecode(time()));
}
/**
* Verify if a password is valid for a specific counter value
*
* @param integer $otp the one-time password
* @param integer $timestamp the timestamp for the a given time, defaults to current time.
* @return bool true if the counter is valid, false otherwise
*/
public function verify($otp, $timestamp = null) {
if($timestamp === null)
$timestamp = time();
return ($otp == $this->at($timestamp));
}
/**
* Returns the uri for a specific secret for totp method.
* Can be encoded as a image for simple configuration in
* Google Authenticator.
*
* @param string $name the name of the account / profile
* @return string the uri for the hmac secret
*/
public function provisioning_uri($name) {
return "otpauth://totp/".urlencode($name)."?secret={$this->secret}";
}
/**
* Transform a timestamp in a counter based on specified internal
*
* @param integer $timestamp
* @return integer the timecode
*/
protected function timecode($timestamp) {
return (int)( (((int)$timestamp * 1000) / ($this->interval * 1000)));
}
}
}