/** * Creates a salted hash from a string. * * @param string $str * String to hash. * * @return string * Returns hashed string, or false on error. */ public static function create($str) { switch (self::$_method) { case self::BCRYPT: $saltRnd = phpsecRand::str(22, self::$charsets['itoa64']); $salt = sprintf('$2a$%s$%s', self::$_bcrypt_cost, $saltRnd); $hash = crypt($str, $salt); break; case self::PBKDF2: $salt = phpsecRand::bytes(64); $hash = phpsecCrypt::pbkdf2($str, $salt, self::$_pbkdf2_c, self::$_pbkdf2_dkLen, self::$_pbkdf2_prf); $hash = sprintf('$pbkdf2$c=%s&dk=%s&f=%s$%s$%s', self::$_pbkdf2_c, self::$_pbkdf2_dkLen, self::$_pbkdf2_prf, base64_encode($hash), base64_encode($salt)); break; case self::SHA256: case self::SHA512: $saltRnd = phpsecRand::str(16, self::$charsets['itoa64']); $salt = sprintf('%srounds=%s$%s', self::$_method, self::$_sha2_c, $saltRnd); $hash = crypt($str, $salt); break; } if (strlen($hash) > 13) { return $hash; } return false; }
/** * Generate and save a one-time-token for a form. Used to protect against * CSRF attacks. * * @param string $name * Name of the form to generate a token for. * * @param integer $ttl * How long the token should be valid in seconds. * * @return string * The token to supply with the form data. */ public static function set($name, $ttl = 3600) { $token = phpsecRand::str(32); /* Save the token to the cahce. */ phpsecCache::cacheSet('token-' . $name, $token, $ttl); return $token; }
/** * Select a pre shared OTP from a list that a user can use. * * @param string $cardId * Card ID to select a OTP from. * * @return integer * OTP ID of a available OTP. */ public static function select($cardId) { $card = self::load($cardId); $available = array_keys($card['usable']); $selected = phpsecRand::int(0, count($available) - 1); return $available[$selected]; }
/** * Verify Yubikey one time password against the Yubico servers. * * @param string $otp * One time password to verify. * * @return boolean * True on valid OTP, false on invalid. If this method returns false * phpsecYubikey::$lastError will contain details. * * @see http://phpseclib.com/manual/yubikey/errors */ public static function verify($otp) { if (self::$_clientId === null || self::$_clientSecret === null) { self::$lastError = 'YUBIKEY_CLIENT_DATA_NEEDED'; return false; } if (!self::validOtp($otp)) { self::$lastError = 'YUBIKEY_INVALID_OTP'; return false; } /* Setup the data needed to make the request. */ $data['otp'] = $otp; $data['id'] = self::$_clientId; $data['nonce'] = phpsecRand::str(20); $data['timestamp'] = 1; $data['h'] = self::sign($data); /* Do the request. */ $response = self::getResponse($data); if ($response === false) { self::$lastError = 'YUBIKEY_SERVER_ERROR'; return false; } /* Check status of response. If not OK return false. */ if ($response['status'] != 'OK') { switch ($response['status']) { case 'REPLAYED_OTP': self::$lastError = 'YUBIKEY_SERVER_REPLAYED_OTP'; break; case 'REPLAYED_REQUEST': self::$lastError = 'YUBIKEY_SERVER_REPLAYED_REQUEST'; break; case 'BAD_OTP': self::$lastError = 'YUBIKEY_SERVER_BAD_OTP'; break; case 'NO_SUCH_CLIENT': self::$lastError = 'YUBIKEY_SERVER_NO_SUCH_CLIENT'; break; case 'BAD_SIGNATURE': self::$lastError = 'YUBIKEY_SERVER_BAD_SIGNATURE'; break; default: self::$lastError = 'YUBIKEY_SERVER_SAYS_NO'; break; } return false; } /* If tokens don't match return false. */ if ($response['otp'] != $otp) { self::$lastError = 'YUBIKEY_NO_MATCH'; return false; } /* Sign the request to see if it matches signature from server. */ $signature = self::sign($response); if ($signature !== $response['h']) { self::$lastError = 'YUBIKEY_BAD_SERVER_SIGNATURE'; return false; } return true; }
/** * Create a list of 64 pre shared one-time-passwords, * or a so called password card. * * This differs from phpsecOtp::generate() because passwords generated by * this function is saved permanent and can be validated on a later time. */ public static function create($length = 6, $num = 32) { $card['list'] = array(); for ($i = 0; $i < $num; $i++) { $card['list'][$i] = phpsecRand::str($length); $card['usable'][$i] = true; } $card = self::save($card); return $card['id']; }
/** * Generate a one-time-password (OTP). The password is only valid for a given time, * and must be delivered to the user instantly. The password is also only valid * for the current session. * * @param string $action * The action to generate a OTP for. This should be as specific as possible. * Used to ensure that the OTP is used for the intended action. * * @param array $data * Optional array of data that belongs to $action. Used to ensure that the action * is performed with the same data as when the OTP was generated. * * @param integer $length * OTP length. * * @param integer $ttl * Time to live for the OTP. In seconds. * * @return string * One time password that should be delivered to the user by for example email or SMS. * */ public static function generate($action, $data = '', $length = 6, $ttl = 480) { $pw = phpsecRand::str($length); $otp['pw'] = phpsecHash::create($pw); if ($data !== null) { $otp['data'] = phpsecHash::create(serialize($data)); } else { $otp['data'] = $data; } phpsecCache::cacheSet('otp-' . $action, $otp, $ttl); return $pw; }
/** * Create a hashed version of a password, safe for storage in a database. * This function return a json encoded array that can be stored directly * into a database. The array has the following layout: * array( * 'hash' => The hash created from the password and a salt. * 'salt' => The salt that was used along with the password to create the hash. * 'algo' => The hashing algorithm used. * ) * * @param string $password * The password to hash. * * @return string * Returns a json encoded array containing the password hash, salt and * some meta data. */ public static function hash($password) { $salt = phpsecRand::bytes(64); switch (self::$_method) { case self::phpsecPw_PBKDF2: $hash = phpsecCrypt::pbkdf2($password, $salt, self::$_pbkdf2_c, self::$_pbkdf2_dkLen, self::$_pbkdf2_prf); /* phpsecCrypt::pbkdf2() returns a binary string. So let's base64 encode it.*/ $hash = base64_encode($hash); /* We append the iteration count, derived key length and PRF as we need this later. */ $algo = 'pbkdf2:' . self::$_pbkdf2_c . ':' . self::$_pbkdf2_dkLen . ':' . self::$_pbkdf2_prf; break; default: $injected = self::inject($password, $salt); $hash = hash(self::$_method, $injected); $algo = self::$_method; } $return = array('hash' => $hash, 'salt' => base64_encode($salt), 'algo' => $algo); return json_encode($return); }
/** * Encrypt data returning a JSON encoded array safe for storage in a database * or file. The array has the following structure before it is encoded: * array( * 'cdata' => 'Encrypted data, Base 64 encoded', * 'iv' => 'Base64 encoded IV', * 'algo' => 'Algorythm used', * 'mode' => 'Mode used', * 'mac' => 'Message Authentication Code' * ) * * @param mixed $data * Data to encrypt. * * @param string $key * Key to encrypt data with. * * @return string * Serialized array containing the encrypted data along with some meta data. */ public static function encrypt($data, $key) { $td = mcrypt_module_open(self::$_algo, '', self::$_mode, ''); /* Check key size. */ $keySize = strlen($key); $keySizes = mcrypt_enc_get_supported_key_sizes($td); if (count($keySizes) > 0) { /* Encryption method requires a specific key size. */ if (!in_array($keySize, $keySizes)) { phpsec::error('Key is out of range. Should be one of: ' . var_export($keySizes, 1)); return false; } } else { /* No spsecific size is needed. */ if ($keySize == 0 || $keySize > mcrypt_enc_get_key_size($td)) { phpsec::error('Key is out of range. Should be: 1 - ' . mcrypt_enc_get_key_size($td) . ' bytes.'); return false; } } /* Create IV. */ $iv = phpsecRand::bytes(mcrypt_enc_get_iv_size($td)); /* Init mcrypt. */ mcrypt_generic_init($td, $key, $iv); /* Prepeare the array with data. */ $serializedData = serialize($data); /* Add padding if enabled. */ if (self::$_padding === true) { $block = mcrypt_enc_get_block_size($td); $serializedData = self::pad($block, $serializedData); } $encrypted['algo'] = self::$_algo; /* Algorithm used to encrypt. */ $encrypted['mode'] = self::$_mode; /* Algorithm mode. */ $encrypted['iv'] = base64_encode($iv); /* Initialization vector, just a bunch of randomness. */ $encrypted['cdata'] = base64_encode(mcrypt_generic($td, $serializedData)); /* The encrypted data. */ $encrypted['mac'] = base64_encode(self::pbkdf2($encrypted['cdata'], $key, 1000, 32)); return json_encode($encrypted); }
/** * Provides a random 32 bit number * if openssl is available, it is cryptographically secure. Otherwise all available entropy is gathered. * @return number */ public static function random() { //If openssl is present, use that to generate random. if (function_exists("openssl_random_pseudo_bytes") && FALSE) { $random32bit = (int) hexdec(bin2hex(openssl_random_pseudo_bytes(64))); } else { if (self::$randomSeed === null) { $entropy = 1; if (function_exists("posix_getpid")) { $entropy *= posix_getpid(); } if (function_exists("memory_get_usage")) { $entropy *= memory_get_usage(); } list($usec, $sec) = explode(" ", microtime()); $usec *= 1000000; $entropy *= $usec; self::$randomSeed = $entropy; mt_srand(self::$randomSeed); } $random32bit = mt_rand(); } return $random32bit; }
public function generate_unique_sequence($entropy = 100) { require_once 'lib/phpsec/phpsec/phpsec.rand.php'; return base64_encode(phpsecRand::bytes($entropy)); }
private function generate_provisional_password() { global $tikilib; require_once 'lib/phpsec/phpsec/phpsec.rand.php'; $site_hash = $tikilib->get_site_hash(); $random_value = phpsecRand::bytes(40); return base64_encode(sha1($random_value . $site_hash, true)); }
/** * Returns a unique identifier in the format spsecified in * OpenID Authentication 2.0 protocol. * For example: 2005-05-15T17:11:51ZUNIQUE * This function is used to generate all unique tokens used by * phpSec. * @see http://openid.net/specs/openid-authentication-2_0.html * * @param integer $length * The total length of the uid. Must be above 25. */ public static function genUid($length = 50) { if ($length < 25) { self::error('Length must be longer than 25'); return false; } $timeStamp = gmdate('Y-m-d\\TH:i:se'); $randLength = $length - strlen($timeStamp); return $timeStamp . phpsecRand::str($randLength); }
/** * Set the cookie with the secret. * * @return true */ private static function setSecret() { self::$_secret = phpsecRand::bytes(32); $cookieParam = session_get_cookie_params(); setcookie(self::$_keyCookie, base64_encode(self::$_secret), $cookieParam['lifetime'], $cookieParam['path'], $cookieParam['domain'], $cookieParam['secure'], $cookieParam['httponly']); return true; }
public function get_site_hash() { global $prefs; if (! isset($prefs['internal_site_hash'])) { require_once 'lib/phpsec/phpsec/phpsec.rand.php'; $hash = base64_encode(phpsecRand::bytes(100)); $this->set_preference('internal_site_hash', $hash); } return $prefs['internal_site_hash']; }