/** * Generates an encrypted random token. * @param \Member $user * @throws \PasswordEncryptor_NotFoundException * @return string */ public static function generate_token($user) { $generator = new \RandomGenerator(); $tokenString = $generator->randomToken(); $e = \PasswordEncryptor::create_for_algorithm('blowfish'); $salt = $e->salt($tokenString); $token = sha1($e->encrypt($tokenString, $salt)) . substr(md5($user->Created . $user->LastEdited . $user->ID), 7); return $token; }
/** * See http://open.silverstripe.org/ticket/3004 * * Handy command for reproducing via CLI on different architectures: * php -r "echo(base_convert(sha1('mypassword'), 16, 36));" */ function testEncrytorLegacyPHPHashCompare() { Config::inst()->update('PasswordEncryptor', 'encryptors', array('test_sha1legacy'=>array('PasswordEncryptor_LegacyPHPHash'=>'sha1'))); $e = PasswordEncryptor::create_for_algorithm('test_sha1legacy'); // precomputed hashes for 'mypassword' from different architectures $amdHash = 'h1fj0a6m4o6k0sosks88oo08ko4gc4s'; $intelHash = 'h1fj0a6m4o0g04ocg00o4kwoc4wowws'; $wrongHash = 'h1fjxxxxxxxxxxxxxxxxxxxxxxxxxxx'; $this->assertTrue($e->compare($amdHash, $intelHash)); $this->assertFalse($e->compare($amdHash, $wrongHash)); }
/** * See http://open.silverstripe.org/ticket/3004 * * Handy command for reproducing via CLI on different architectures: * php -r "echo(base_convert(sha1('mypassword'), 16, 36));" */ function testEncrytorLegacyPHPHashCompare() { PasswordEncryptor::register('test_sha1legacy', 'PasswordEncryptor_LegacyPHPHash("sha1")'); $e = PasswordEncryptor::create_for_algorithm('test_sha1legacy'); // precomputed hashes for 'mypassword' from different architectures $amdHash = 'h1fj0a6m4o6k0sosks88oo08ko4gc4s'; $intelHash = 'h1fj0a6m4o0g04ocg00o4kwoc4wowws'; $wrongHash = 'h1fjxxxxxxxxxxxxxxxxxxxxxxxxxxx'; $this->assertTrue($e->compare($amdHash, $intelHash)); $this->assertFalse($e->compare($amdHash, $wrongHash)); }
/** * Changes a users password * @param {stdClass} $data Data passed from ActionScript * @return {array} Returns a standard response array */ public function changePassword($data) { $response = CodeBank_ClientAPI::responseBase(); try { $member = Member::currentUser(); $e = PasswordEncryptor::create_for_algorithm($member->PasswordEncryption); if (!$e->check($member->Password, $data->currPassword, $member->Salt, $member)) { $response['status'] = 'EROR'; $response['message'] = _t('CodeBankAPI.CURRENT_PASSWORD_MATCH', '_Current password does not match'); return $response; } if (!$member->changePassword($data->password)) { $response['status'] = 'EROR'; $response['message'] = _t('CodeBankAPI.NEW_PASSWORD_NOT_VALID', '_New password is not valid'); return $response; } $response['status'] = 'HELO'; $response['message'] = _t('CodeBankAPI.PASSWORD_CHANGED', '_User\'s password changed successfully'); } catch (Exception $e) { $response['status'] = 'EROR'; $response['message'] = _t('CodeBankAPI.SERVER_ERROR', '_Server error has occured, please try again later'); } return $response; }
/** * Utility for generating secure password hashes for this member. */ public function encryptWithUserSettings($string) { if (!$string) { return null; } // If the algorithm or salt is not available, it means we are operating // on legacy account with unhashed password. Do not hash the string. if (!$this->PasswordEncryption) { return $string; } // We assume we have PasswordEncryption and Salt available here. $e = PasswordEncryptor::create_for_algorithm($this->PasswordEncryption); return $e->encrypt($string, $this->Salt); }
/** * Encrypt a password according to the current password encryption settings. * If the settings are so that passwords shouldn't be encrypted, the * result is simple the clear text password with an empty salt except when * a custom algorithm ($algorithm parameter) was passed. * * @param string $password The password to encrypt * @param string $salt Optional: The salt to use. If it is not passed, but * needed, the method will automatically create a * random salt that will then be returned as return value. * @param string $algorithm Optional: Use another algorithm to encrypt the * password (so that the encryption algorithm can be changed over the time). * @param Member $member Optional * @return mixed Returns an associative array containing the encrypted * password and the used salt in the form: * <code> * array( * 'password' => string, * 'salt' => string, * 'algorithm' => string, * 'encryptor' => PasswordEncryptor instance * ) * </code> * If the passed algorithm is invalid, FALSE will be returned. * * @see encrypt_passwords() */ public static function encrypt_password($password, $salt = null, $algorithm = null, $member = null) { // Fall back to the default encryption algorithm if (!$algorithm) { $algorithm = self::config()->password_encryption_algorithm; } $e = PasswordEncryptor::create_for_algorithm($algorithm); // New salts will only need to be generated if the password is hashed for the first time $salt = $salt ? $salt : $e->salt($password); return array('password' => $e->encrypt($password, $salt, $member), 'salt' => $salt, 'algorithm' => $algorithm, 'encryptor' => $e); }
/** * Check if the given password is the same as the one stored in this record. * See {@link Member->checkPassword()}. * * @param String $password Cleartext password * @return Boolean */ public function checkPassword($password) { $e = PasswordEncryptor::create_for_algorithm($this->PasswordEncryption); return $e->check($this->Password, $password, $this->Salt, $this->Member()); }
/** * Generates an encrypted random token * and an expiry date * * @param boolean $expired Set to true to generate an outdated token * @return array token data array('token' => HASH, 'expire' => EXPIRY_DATE) */ private function generateToken($expired = false) { $life = $this->tokenConfig['life']; if (!$expired) { $expire = time() + $life; } else { $expire = time() - $life * 2; } $generator = new RandomGenerator(); $tokenString = $generator->randomToken(); $e = PasswordEncryptor::create_for_algorithm('blowfish'); //blowfish isn't URL safe and maybe too long? $salt = $e->salt($tokenString); $token = $e->encrypt($tokenString, $salt); return array('token' => substr($token, 7), 'expire' => $expire); }
/** * Encrypt a password according to the current password encryption settings. * If the settings are so that passwords shouldn't be encrypted, the * result is simple the clear text password with an empty salt except when * a custom algorithm ($algorithm parameter) was passed. * * @param string $password The password to encrypt * @param string $salt Optional: The salt to use. If it is not passed, but * needed, the method will automatically create a * random salt that will then be returned as return value. * @param string $algorithm Optional: Use another algorithm to encrypt the * password (so that the encryption algorithm can be changed over the time). * @param Member $member Optional * @return mixed Returns an associative array containing the encrypted * password and the used salt in the form: * <code> * array( * 'password' => string, * 'salt' => string, * 'algorithm' => string, * 'encryptor' => PasswordEncryptor instance * ) * </code> * If the passed algorithm is invalid, FALSE will be returned. * * @see encrypt_passwords() * @see set_password_encryption_algorithm() */ static function encrypt_password($password, $salt = null, $algorithm = null, $member = null) { if (strlen(trim($password)) == 0 || !$algorithm && self::$encryptPasswords == false) { $algorithm = 'none'; } else { // Fall back to the default encryption algorithm if (!$algorithm) { $algorithm = self::$encryptionAlgorithm; } } $e = PasswordEncryptor::create_for_algorithm($algorithm); // New salts will only need to be generated if the password is hashed for the first time $salt = $salt ? $salt : $e->salt($password); return array('password' => $e->encrypt($password, $salt, $member), 'salt' => $salt, 'algorithm' => $algorithm, 'encryptor' => $e); }
/** * Check if the passed password matches the stored one (if the member is not locked out). * * @param string $password * @return ValidationResult */ public function checkPassword($password) { $result = $this->canLogIn(); $e = PasswordEncryptor::create_for_algorithm($this->PasswordEncryption); if (!$e->check($this->Password, $password, $this->Salt, $this)) { $result->error(_t('Member.ERRORWRONGCRED', 'That doesn\'t seem to be the right e-mail address or password. Please try again.')); } return $result; }
/** * Encrypt a password according to the current password encryption settings. * If the settings are so that passwords shouldn't be encrypted, the * result is simple the clear text password with an empty salt except when * a custom algorithm ($algorithm parameter) was passed. * * @param string $password The password to encrypt * @param string $salt Optional: The salt to use. If it is not passed, but * needed, the method will automatically create a * random salt that will then be returned as return value. * @param string $algorithm Optional: Use another algorithm to encrypt the * password (so that the encryption algorithm can be changed over the time). * @param Member $member Optional * @return mixed Returns an associative array containing the encrypted * password and the used salt in the form: * <code> * array( * 'password' => string, * 'salt' => string, * 'algorithm' => string, * 'encryptor' => PasswordEncryptor instance * ) * </code> * If the passed algorithm is invalid, FALSE will be returned. * * @see encrypt_passwords() * @see set_password_encryption_algorithm() */ static function encrypt_password($password, $salt = null, $algorithm = null, $member = null) { if( // if the password is empty, don't encrypt strlen(trim($password)) == 0 // if no algorithm is provided and no default is set, don't encrypt || (!$algorithm) ) { $algorithm = 'none'; } else { // Fall back to the default encryption algorithm if(!$algorithm) $algorithm = self::$encryptionAlgorithm; } $e = PasswordEncryptor::create_for_algorithm($algorithm); // New salts will only need to be generated if the password is hashed for the first time $salt = ($salt) ? $salt : $e->salt($password); return array( 'password' => $e->encrypt($password, $salt, $member), 'salt' => $salt, 'algorithm' => $algorithm, 'encryptor' => $e ); }