Exemple #1
0
 public function twoFactor(array $envData)
 {
     $userId = self::getUserId($envData['common_name']);
     // use username field to specify OTP type, for now we only support 'totp'
     $otpType = $envData['username'];
     if ('totp' !== $otpType) {
         throw new TwoFactorException('invalid OTP type specified in username field');
     }
     $otpKey = $envData['password'];
     // validate the OTP key
     if (0 === preg_match('/^[0-9]{6}$/', $otpKey)) {
         throw new TwoFactorException('invalid OTP key format specified');
     }
     $dataDir = sprintf('%s/data/%s', $this->baseDir, $envData['INSTANCE_ID']);
     if (false === ($otpSecret = @file_get_contents(sprintf('%s/users/otp_secrets/%s', $dataDir, $userId)))) {
         throw new TwoFactorException('no OTP secret registered');
     }
     $otp = new Otp();
     if ($otp->checkTotp(Base32::decode($otpSecret), $otpKey)) {
         if (false === $this->otpLog->record($userId, $otpKey, time())) {
             throw new TwoFactorException('OTP replayed');
         }
     } else {
         throw new TwoFactorException('invalid OTP key');
     }
 }
 public function calculateCode($secret, $timeSlice = null)
 {
     // If we haven't been fed a timeSlice, then get one.
     // It looks a bit unclean doing it like this, but it allows us to write testable code
     $timeSlice = $timeSlice ? $timeSlice : $this->getTimeSlice();
     // Packs the timeslice as a "unsigned long" (always 32 bit, big endian byte order)
     $timeSlice = pack("N", $timeSlice);
     // Then pad it with the null terminator
     $timeSlice = str_pad($timeSlice, 8, chr(0), STR_PAD_LEFT);
     // Hash it with SHA1. The spec does offer the idea of other algorithms, but notes that the authenticator is currently
     // ignoring it...
     $hash = hash_hmac("SHA1", $timeSlice, Base32::decode($secret), true);
     // Last 4 bits are an offset apparently
     $offset = ord(substr($hash, -1)) & 0xf;
     // Grab the last 4 bytes
     $result = substr($hash, $offset, 4);
     // Unpack it again
     $value = unpack('N', $result)[1];
     // Only 32 bits
     $value = $value & 0x7fffffff;
     // Modulo down to the right number of digits
     $modulo = pow(10, $this->codeLength);
     // Finally, pad out the string with 0s
     return str_pad($value % $modulo, $this->codeLength, '0', STR_PAD_LEFT);
 }
 /**
  * @param Seed|string|null
  * @param ITimestampProvider|int|null
  * @param int
  * @throws \Exception
  */
 public function __construct($seed = NULL, $timestamp = NULL, $period = 30)
 {
     if ($seed === NULL) {
         $this->seed = Seed::generate();
     } elseif (is_string($seed) && ($decoded = Base32::decode($seed)) !== '') {
         $this->seed = new Seed($decoded);
     } elseif ($seed instanceof Seed) {
         $this->seed = $seed;
     } else {
         throw new \Exception('Seed must be valid base32 encoded string or instance of Seed.');
     }
     if ($timestamp === NULL) {
         $this->timestampProvider = SystemTimestampProvider::getInstance();
     } elseif (is_int($timestamp) || ctype_digit($timestamp)) {
         $this->timestampProvider = new ConstantTimestampProvider((int) $timestamp);
     } elseif ($timestamp instanceof ITimestampProvider) {
         $this->timestampProvider = $timestamp;
     } else {
         throw new \Exception('Timestamp must be integer or instance of ITimestampProvider.');
     }
     if ((is_int($period) || ctype_digit($period)) && $period > 0) {
         $this->period = (int) $period;
     } else {
         throw new \Exception('Period must be integer greater then 0.');
     }
 }
 /**
  * @expectedException \SURFnet\VPN\Server\Exception\TwoFactorException
  * @expectedExceptionMessage OTP replayed
  */
 public function testTwoFactorReplay()
 {
     $o = new Otp();
     $otpKey = $o->totp(Base32::decode('QPXDFE7G7VNRR4BH'));
     $c = new TwoFactor(__DIR__, $this->otpLog);
     $c->twoFactor(['INSTANCE_ID' => 'vpn.example', 'POOL_ID' => 'internet', 'common_name' => 'foo_xyz', 'username' => 'totp', 'password' => $otpKey]);
     // replay
     $c->twoFactor(['INSTANCE_ID' => 'vpn.example', 'POOL_ID' => 'internet', 'common_name' => 'foo_xyz', 'username' => 'totp', 'password' => $otpKey]);
 }
 /**
  * Tests Base32->decode()
  *
  * Testing test vectors according to RFC 4648
  * http://www.ietf.org/rfc/rfc4648.txt
  */
 public function testDecode()
 {
     // RFC test vectors say that empty string returns empty string
     $this->assertEquals('', Base32::decode(''));
     // these strings are taken from the RFC
     $this->assertEquals('f', Base32::decode('MY======'));
     $this->assertEquals('fo', Base32::decode('MZXQ===='));
     $this->assertEquals('foo', Base32::decode('MZXW6==='));
     $this->assertEquals('foob', Base32::decode('MZXW6YQ='));
     $this->assertEquals('fooba', Base32::decode('MZXW6YTB'));
     $this->assertEquals('foobar', Base32::decode('MZXW6YTBOI======'));
 }
 /**
  * Ajout de $secret en DB et activation l'authentification à 2 facteurs
  */
 public function totp_post(Request $request)
 {
     $otp = new Otp();
     $secret = session()->get('secret');
     $key = $request->get("code");
     $user = $this->auth->user();
     if ($otp->checkTotp(Base32::decode($secret), $key)) {
         DB::table('users')->where('id', $user->id)->update(array('totp_key' => $secret));
         Session::forget('code');
         return redirect(url('profil'))->with('success', 'L\'authentification à 2 facteurs à bien été activer');
     } else {
         return redirect(url('profil/totp'))->with('error', 'Ce code ne correspond pas, veuillez recommencer l\'opération');
     }
 }
Exemple #7
0
 /**
  * Tests Base32->decode()
  *
  * Testing test vectors according to RFC 4648
  * http://www.ietf.org/rfc/rfc4648.txt
  */
 public function testDecode()
 {
     // RFC test vectors say that empty string returns empty string
     $this->assertEquals('', Base32::decode(''));
     // these strings are taken from the RFC
     $this->assertEquals('f', Base32::decode('MY======'));
     $this->assertEquals('fo', Base32::decode('MZXQ===='));
     $this->assertEquals('foo', Base32::decode('MZXW6==='));
     $this->assertEquals('foob', Base32::decode('MZXW6YQ='));
     $this->assertEquals('fooba', Base32::decode('MZXW6YTB'));
     $this->assertEquals('foobar', Base32::decode('MZXW6YTBOI======'));
     // Decoding a string made up entirely of invalid characters
     $this->assertEquals('', Base32::decode('8908908908908908'));
 }
 /**
  * Get the code from the time and secret
  *
  * @param string   $secret
  * @param int|null $time
  *
  * @return string
  */
 public function getCode($secret, $time = null)
 {
     if (!$time) {
         $time = floor(time() / 30);
     }
     $secret = Base32::decode($secret);
     $time = pack('N', $time);
     $time = str_pad($time, 8, chr(0), STR_PAD_LEFT);
     $hash = hash_hmac('sha1', $time, $secret, true);
     $offset = ord(substr($hash, -1));
     $offset = $offset & 0xf;
     $tHash = $this->hashToInt($hash, $offset) & 0x7fffffff;
     $pin = str_pad($tHash % $this->pinModulo, 6, "0", STR_PAD_LEFT);
     return $pin;
 }
Exemple #9
0
 public function store()
 {
     $response = array();
     $otp = new Otp();
     $secret = Input::get('s');
     $key = Input::get('txCodigo');
     if ($otp->checkTotp(Base32::decode($secret), $key, 0)) {
         DB::table('authusuarios')->where('usuarioid', Auth::user()->usuarioid)->update(['twostepsecret' => $secret]);
         $response['result'] = true;
         return json_encode($response);
     } else {
         $response['result'] = false;
         return json_encode($response);
     }
 }
Exemple #10
0
 public static function getCode($secret, $timeSlice = null)
 {
     if ($timeSlice === null) {
         $timeSlice = floor(time() / self::TIME_STEP);
     }
     $secretKey = \Base32\Base32::decode($secret);
     $binaryTimestamp = pack('N*', 0) . pack('N*', $timeSlice);
     $hmac = hash_hmac('SHA1', $binaryTimestamp, $secretKey, true);
     $offset = ord(substr($hmac, -1)) & 0xf;
     $part = substr($hmac, $offset, 4);
     $unpack_value_array = unpack('N', $part);
     $unpack_value = $unpack_value_array[1];
     $seed = $unpack_value & 0x7fffffff;
     $pow = pow(10, self::CODE_LENGTH);
     return str_pad($seed % $pow, self::CODE_LENGTH, '0', STR_PAD_LEFT);
 }
 public function authenticate($username, $password, $htop_value)
 {
     if (isset($this->credentials[$username])) {
         list($user_password, $user_htop_secret) = $this->credentials[$username];
         if ($user_password === $password) {
             $otp = new Otp();
             if ($otp->checkTotp(Base32::decode($user_htop_secret), $htop_value)) {
                 $this->session->username = $username;
                 $this->session->valid_host = $_SERVER['HTTP_HOST'];
                 $this->session->authenticated = true;
                 return true;
             }
         }
     }
     return false;
 }
Exemple #12
0
 /**
  * Onion constructor.
  * @param string $onionHost
  */
 public function __construct($onionHost)
 {
     $array = explode(".", $onionHost);
     if (count($array) !== 2) {
         throw new \InvalidArgumentException('Malformed onion address');
     }
     list($ident, $onion) = $array;
     if ($onion !== 'onion') {
         throw new \InvalidArgumentException('Malformed onion address');
     }
     $decoded = Base32::decode($ident);
     if (strlen($decoded) !== 10) {
         throw new \InvalidArgumentException('Malformed onion address');
     }
     $this->identifier = $decoded;
     $this->host = $onionHost;
 }
 /**
  * Validates a TOTP request.
  *
  * @todo Prevent TOTP replay attack.
  * @param string $key The TOTP token sent in.
  * @param string $secret The TOTP secret.
  * @return bool
  */
 public function validateTOTP($key, $secret)
 {
     $otp = new Otp();
     return $otp->checkTotp(Base32::decode($secret), $key);
 }
Exemple #14
0
    $user_u = $DB->execute("UPDATE users SET password = :password WHERE iduser = :iduser", array("iduser" => $iduser, "password" => $en_pass));
    if ($user_u == 1) {
        $text = "Le mot de passe de l'utilisateur <strong>" . $username . "</strong> à été changer avec succès !";
        $addNotif = $DB->execute("INSERT INTO notif(idnotif, iduser, type, notification, date_notification, vu) VALUES (NULL , :iduser, :type, :notification, :date_notification, :vu)", array("iduser" => $iduser, "type" => 2, "notification" => $user->prenom_user . " à modifier le mot de passe de sont Espace.", "date_notification" => $date_format->format_strt(date("d-m-Y H:i:s")), "vu" => 0));
        $fonction->redirect("profil", "", "", "success", "edit-password", $text);
    } else {
        $fonction->redirect("error", "", "", "code", "USR4", "");
    }
}
if (isset($_POST['action']) && $_POST['action'] == 'active_totp') {
    session_start();
    require "../application/classe.php";
    $iduser = $user->iduser;
    $username = $user->username;
    $otp = new Otp();
    if ($otp->checkTotp(Base32::decode($_SESSION['user']['totp_secret']), $_POST['code'])) {
        $user_u = $DB->execute("UPDATE users SET totp = 1, totp_token = :totp_token WHERE iduser = :iduser", array("totp_token" => $_SESSION['user']['totp_secret'], "iduser" => $iduser));
        $_SESSION['user']['totp_secret'] = "";
        if ($user_u == 1) {
            $text = "L'authentificateur 2 Facteur à été activé pour l'utilisateur <strong>" . $username . "</strong>.";
            $addNotif = $DB->execute("INSERT INTO notif(idnotif, iduser, type, notification, date_notification, vu) VALUES (NULL , :iduser, :type, :notification, :date_notification, :vu)", array("iduser" => $iduser, "type" => 1, "notification" => $user->prenom_user . " à activé l'authentification à 2 facteur.", "date_notification" => $date_format->format_strt(date("d-m-Y H:i:s")), "vu" => 0));
            $fonction->redirect("profil", "", "", "success", "active_totp", $text);
        } else {
            $fonction->redirect("error", "", "", "code", "USR5", "");
        }
    } else {
        $fonction->redirect("profil", "", "", "error", "active_totp", "Ce code ne correspond pas !!!");
    }
}
if (isset($_GET['action']) && $_GET['action'] == 'desactive_totp') {
    session_start();
Exemple #15
0
 public function totp(Request $request)
 {
     $user_id = session()->get('user_id');
     $key = $request->get("code");
     if (empty($user_id)) {
         return redirect('/auth/login');
     }
     $otp = new Otp();
     $user = User::where('id', $user_id)->first();
     if ($key) {
         if ($otp->checkTotp(Base32::decode($user->totp_key), $key)) {
             $this->auth->login($user, $request->has('remember'));
             return redirect()->intended($this->redirectPath());
         } else {
             return redirect(url('totp'))->with('error', 'Ce code ne correspond pas, veuillez recommencer l\'opération');
         }
     }
     return view('auth.totp')->with('error', 'Ce compte à activer \'authentification à 2 facteurs');
 }
Exemple #16
0
 /**
  * Check 2FA
  *
  * @access public
  */
 public function check()
 {
     $user = $this->getUser();
     $this->checkCurrentUser($user);
     $otp = new Otp();
     $values = $this->request->getValues();
     if (!empty($values['code']) && $otp->checkTotp(Base32::decode($user['twofactor_secret']), $values['code'])) {
         $this->sessionStorage->postAuth['validated'] = true;
         $this->flash->success(t('The two factor authentication code is valid.'));
         $this->response->redirect($this->helper->url->to('app', 'index'));
     } else {
         $this->flash->failure(t('The two factor authentication code is not valid.'));
         $this->response->redirect($this->helper->url->to('twofactor', 'code'));
     }
 }
Exemple #17
0
 public function setSecret($value)
 {
     if (strlen($value) !== $this->secretLength) {
         throw new InvalidConfigException('Otp::setSecret length is not equal to ' . $this->secretLength . ' ([\'length\'] component settenings)');
     } elseif (strlen(Base32::decode($value)) < 1) {
         throw new InvalidConfigException('Otp::setSecret incorect, encode as Base32');
     }
     $this->otp->setSecret($value);
     $this->_secret = $value;
 }
 /**
  * @param  int $timeIndex
  * @return string
  */
 public function getCode($timeIndex = null)
 {
     if (is_null($timeIndex)) {
         $timeIndex = $this->getTimeIndex();
     }
     $secretkey = Base32::decode($this->secretKey);
     $hm = hash_hmac('SHA1', chr(0) . chr(0) . chr(0) . chr(0) . pack('N*', $timeIndex), $secretkey, true);
     $value = unpack('N', substr($hm, ord(substr($hm, -1)) & 0xf, 4));
     $value = $value[1] & 0x7fffffff;
     return str_pad($value % pow(10, static::CODE_LENGTH), static::CODE_LENGTH, '0', STR_PAD_LEFT);
 }
Exemple #19
0
</form>

<br />
Output:<br />
<br />


<?php 
if (isset($_POST['otpkey'])) {
    // Sanatizing, this should take care of it
    $key = preg_replace('/[^0-9]/', '', $_POST['otpkey']);
    // Standard is 6 for keys, but can be changed with setDigits on $otp
    if (strlen($key) == 6) {
        // Remember that the secret is a base32 string that needs decoding
        // to use it here!
        if ($otp->checkTotp(Base32::decode($secret), $key)) {
            echo 'Key correct!';
            // Add here something that makes note of this key and will not allow
            // the use of it, for this user for the next 2 minutes. This way you
            // prevent a replay attack. Otherwise your OTP is missing one of the
            // key features it can bring in security to your application!
        } else {
            echo 'Wrong key!';
        }
    } else {
        echo 'Key not the correct size';
    }
}
?>

</body>
Exemple #20
0
 /**
  * @throws \InvalidArgumentException
  *
  * @return string
  */
 private function getDecodedSecret()
 {
     $secret = Base32::decode($this->getSecret());
     return $secret;
 }
 /**
  * @return string
  */
 private function byteSecret()
 {
     return Base32::decode($this->getSecret());
 }
Exemple #22
0
 public static function generate($length = 16)
 {
     return new static(Base32::decode(Strings::random($length, 'A-Z2-7')));
 }
Exemple #23
0
 /**
  * Authenticate the user
  *
  * @access public
  * @return boolean
  */
 public function authenticate()
 {
     $otp = new Otp();
     return $otp->checkTotp(Base32::decode($this->secret), $this->code);
 }
Exemple #24
0
 public function __toString()
 {
     $id = \Base32\Base32::decode(strtoupper(str_replace('-', '', $this->_id)));
     return pack('N', strlen($id)) . $id . pack('N', count($this->_addresses)) . implode('', $this->_addresses);
 }
Exemple #25
0
 public function fromBase32String()
 {
     return Base32::decode($this->digest);
 }
Exemple #26
0
 /**
  * Returns the binary value of the base32 encoded secret skey
  * 
  * @return binary secret key
  */
 public function decode_key()
 {
     return \Base32\Base32::decode($this->skey);
 }