2009-11-06 03:23:21 +01:00
|
|
|
<?php
|
2016-06-15 06:03:16 +02:00
|
|
|
|
2016-06-23 01:37:22 +02:00
|
|
|
namespace SilverStripe\Security;
|
|
|
|
|
2016-08-19 00:51:35 +02:00
|
|
|
use SilverStripe\Core\Config\Config;
|
2016-06-23 01:37:22 +02:00
|
|
|
use ReflectionClass;
|
|
|
|
|
2009-11-06 03:23:21 +01:00
|
|
|
/**
|
|
|
|
* Allows pluggable password encryption.
|
|
|
|
* By default, this might be PHP's integrated sha1()
|
|
|
|
* function, but could also be more sophisticated to facilitate
|
|
|
|
* password migrations from other systems.
|
|
|
|
* Use {@link register()} to add new implementations.
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2009-11-06 03:23:21 +01:00
|
|
|
* Used in {@link Security::encrypt_password()}.
|
|
|
|
*/
|
|
|
|
abstract class PasswordEncryptor {
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-11-06 03:23:21 +01:00
|
|
|
/**
|
|
|
|
* @var array
|
2013-03-21 19:48:54 +01:00
|
|
|
* @config
|
2009-11-06 03:23:21 +01:00
|
|
|
*/
|
2013-03-21 19:48:54 +01:00
|
|
|
private static $encryptors = array();
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-11-06 03:23:21 +01:00
|
|
|
/**
|
2016-06-23 01:37:22 +02:00
|
|
|
* @return array Map of encryptor code to the used class.
|
2009-11-06 03:23:21 +01:00
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public static function get_encryptors() {
|
2016-06-23 01:37:22 +02:00
|
|
|
return Config::inst()->get('SilverStripe\\Security\\PasswordEncryptor', 'encryptors');
|
2009-11-06 03:23:21 +01:00
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-11-06 03:23:21 +01:00
|
|
|
/**
|
|
|
|
* @param String $algorithm
|
2012-04-07 04:59:55 +02:00
|
|
|
* @return PasswordEncryptor
|
|
|
|
* @throws PasswordEncryptor_NotFoundException
|
2009-11-06 03:23:21 +01:00
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public static function create_for_algorithm($algorithm) {
|
2012-04-07 04:59:55 +02:00
|
|
|
$encryptors = self::get_encryptors();
|
|
|
|
if(!isset($encryptors[$algorithm])) {
|
2009-11-06 03:23:21 +01:00
|
|
|
throw new PasswordEncryptor_NotFoundException(
|
|
|
|
sprintf('No implementation found for "%s"', $algorithm)
|
|
|
|
);
|
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2012-04-07 04:59:55 +02:00
|
|
|
$class=key($encryptors[$algorithm]);
|
2009-11-06 03:23:21 +01:00
|
|
|
if(!class_exists($class)) {
|
|
|
|
throw new PasswordEncryptor_NotFoundException(
|
|
|
|
sprintf('No class found for "%s"', $class)
|
|
|
|
);
|
|
|
|
|
2012-04-07 04:59:55 +02:00
|
|
|
}
|
|
|
|
$refClass = new ReflectionClass($class);
|
|
|
|
if(!$refClass->getConstructor()) {
|
|
|
|
return new $class;
|
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2012-04-07 04:59:55 +02:00
|
|
|
$arguments = $encryptors[$algorithm];
|
|
|
|
return($refClass->newInstanceArgs($arguments));
|
2009-11-06 03:23:21 +01:00
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-11-06 03:23:21 +01:00
|
|
|
/**
|
|
|
|
* Return a string value stored in the {@link Member->Password} property.
|
|
|
|
* The password should be hashed with {@link salt()} if applicable.
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2009-11-06 03:23:21 +01:00
|
|
|
* @param String $password Cleartext password to be hashed
|
|
|
|
* @param String $salt (Optional)
|
|
|
|
* @param Member $member (Optional)
|
|
|
|
* @return String Maximum of 512 characters.
|
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
abstract public function encrypt($password, $salt = null, $member = null);
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2009-11-06 03:23:21 +01:00
|
|
|
/**
|
|
|
|
* Return a string value stored in the {@link Member->Salt} property.
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2010-12-05 01:37:35 +01:00
|
|
|
* @uses RandomGenerator
|
2014-08-15 08:53:05 +02:00
|
|
|
*
|
2016-06-23 01:37:22 +02:00
|
|
|
* @param string $password Cleartext password
|
2009-11-06 03:23:21 +01:00
|
|
|
* @param Member $member (Optional)
|
2016-06-23 01:37:22 +02:00
|
|
|
* @return string Maximum of 50 characters
|
2009-11-06 03:23:21 +01:00
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function salt($password, $member = null) {
|
2010-12-05 01:37:35 +01:00
|
|
|
$generator = new RandomGenerator();
|
2012-11-08 04:33:19 +01:00
|
|
|
return substr($generator->randomToken('sha1'), 0, 50);
|
2009-11-06 03:23:21 +01:00
|
|
|
}
|
2014-08-15 08:53:05 +02:00
|
|
|
|
2012-05-07 05:03:53 +02:00
|
|
|
/**
|
|
|
|
* This usually just returns a strict string comparison,
|
|
|
|
* but is necessary for retain compatibility with password hashed
|
|
|
|
* with flawed algorithms - see {@link PasswordEncryptor_LegacyPHPHash} and
|
|
|
|
* {@link PasswordEncryptor_Blowfish}
|
2016-06-23 01:37:22 +02:00
|
|
|
*
|
|
|
|
* @param string $hash
|
|
|
|
* @param string $password
|
|
|
|
* @param string $salt
|
|
|
|
* @param Member $member
|
|
|
|
* @return bool
|
2012-05-07 05:03:53 +02:00
|
|
|
*/
|
2012-09-19 12:07:39 +02:00
|
|
|
public function check($hash, $password, $salt = null, $member = null) {
|
2012-05-07 05:03:53 +02:00
|
|
|
return $hash === $this->encrypt($password, $salt, $member);
|
|
|
|
}
|
2009-11-06 03:23:21 +01:00
|
|
|
}
|