ILIAS  trunk Revision v11.0_alpha-1749-g1a06bdef097
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
ilBcryptPasswordEncoder Class Reference
+ Inheritance diagram for ilBcryptPasswordEncoder:
+ Collaboration diagram for ilBcryptPasswordEncoder:

Public Member Functions

 __construct (array $config=[])
 
 getDataDirectory ()
 
 setDataDirectory (string $data_directory)
 
 isBackwardCompatibilityEnabled ()
 
 setBackwardCompatibility (bool $backward_compatibility)
 Set the backward compatibility $2a$ instead of $2y$ for PHP 5.3.7+. More...
 
 isSecurityFlawIgnored ()
 
 setIsSecurityFlawIgnored (bool $is_security_flaw_ignored)
 
 getClientSalt ()
 
 setClientSalt (?string $client_salt)
 
 encodePassword (string $raw, string $salt)
 Encodes the raw password. More...
 
 isPasswordValid (string $encoded, string $raw, string $salt)
 Checks a raw password against an encoded password. More...
 
 getName ()
 Returns a unique name/id of the concrete password encoder. More...
 
 requiresSalt ()
 Returns whether the encoder requires a salt. More...
 
 requiresReencoding (string $encoded)
 Returns whether the encoded password needs to be re-encoded. More...
 
 getClientSaltLocation ()
 
- Public Member Functions inherited from ilBcryptPhpPasswordEncoder
 __construct (array $config=[])
 
 benchmarkCost (float $time_target=0.05)
 
 getName ()
 Returns a unique name/id of the concrete password encoder. More...
 
 getCosts ()
 
 setCosts (string $costs)
 
 encodePassword (string $raw, string $salt)
 Encodes the raw password. More...
 
 isPasswordValid (string $encoded, string $raw, string $salt)
 Checks a raw password against an encoded password. More...
 
 requiresReencoding (string $encoded)
 Returns whether the encoded password needs to be re-encoded. More...
 
- Public Member Functions inherited from ilBasePasswordEncoder
 isSupportedByRuntime ()
 Returns whether the encoder is supported by the runtime (PHP, HHVM, ...) More...
 
 requiresSalt ()
 Returns whether the encoder requires a salt. More...
 
 requiresReencoding (string $encoded)
 Returns whether the encoded password needs to be re-encoded. More...
 

Data Fields

const SALT_STORAGE_FILENAME = 'pwsalt.txt'
 

Private Member Functions

 isBcryptSupported ()
 
 encode (string $raw, string $userSecret)
 
 check (string $encoded, string $raw, string $salt)
 
 readClientSalt ()
 
 generateClientSalt ()
 
 storeClientSalt ()
 

Private Attributes

const MIN_SALT_SIZE = 16
 
string $client_salt = null
 
bool $is_security_flaw_ignored = false
 
bool $backward_compatibility = false
 
string $data_directory = ''
 

Additional Inherited Members

- Protected Member Functions inherited from ilBasePasswordEncoder
 comparePasswords (string $knownString, string $userString)
 Compares two passwords. More...
 
 isPasswordTooLong (string $password)
 

Detailed Description

Definition at line 27 of file class.ilBcryptPasswordEncoder.php.

Constructor & Destructor Documentation

◆ __construct()

ilBcryptPasswordEncoder::__construct ( array  $config = [])
Parameters
array<string,mixed>$config
Exceptions
ilPasswordException

Definition at line 44 of file class.ilBcryptPasswordEncoder.php.

References ILIAS\GlobalScreen\Provider\__construct(), readClientSalt(), setDataDirectory(), and setIsSecurityFlawIgnored().

45  {
46  foreach ($config as $key => $value) {
47  $key = strtolower($key);
48  if ($key === 'ignore_security_flaw') {
49  $this->setIsSecurityFlawIgnored($value);
50  } elseif ($key === 'data_directory') {
51  $this->setDataDirectory($value);
52  }
53  }
54 
55  parent::__construct($config);
56  $this->readClientSalt();
57  }
setIsSecurityFlawIgnored(bool $is_security_flaw_ignored)
setDataDirectory(string $data_directory)
__construct(Container $dic, ilPlugin $plugin)
+ Here is the call graph for this function:

Member Function Documentation

◆ check()

ilBcryptPasswordEncoder::check ( string  $encoded,
string  $raw,
string  $salt 
)
private

Definition at line 185 of file class.ilBcryptPasswordEncoder.php.

References ilBasePasswordEncoder\comparePasswords().

Referenced by isPasswordValid().

185  : bool
186  {
187  $hashedPassword = hash_hmac(
188  'whirlpool',
189  str_pad($raw, strlen($raw) * 4, sha1($salt), STR_PAD_BOTH),
190  (string) $this->client_salt,
191  true
192  );
193 
194  return $this->comparePasswords($encoded, crypt($hashedPassword, substr($encoded, 0, 30)));
195  }
comparePasswords(string $knownString, string $userString)
Compares two passwords.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ encode()

ilBcryptPasswordEncoder::encode ( string  $raw,
string  $userSecret 
)
private

Check for security flaw in the bcrypt implementation used by crypt()

See also
http://php.net/security/crypt_blowfish.php

Definition at line 144 of file class.ilBcryptPasswordEncoder.php.

References $client_salt, ilBcryptPhpPasswordEncoder\getCosts(), and isBcryptSupported().

Referenced by encodePassword().

144  : string
145  {
146  $clientSecret = $this->client_salt;
147  $hashedPassword = hash_hmac(
148  'whirlpool',
149  str_pad($raw, strlen($raw) * 4, sha1($userSecret), STR_PAD_BOTH),
150  $clientSecret ?? '',
151  true
152  );
153  $salt = substr(
154  str_shuffle(str_repeat('./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', 22)),
155  0,
156  22
157  );
158 
163  if ($this->isBcryptSupported() && !$this->backward_compatibility) {
164  $prefix = '$2y$';
165  } else {
166  $prefix = '$2a$';
167  // check if the password contains 8-bit character
168  if (!$this->is_security_flaw_ignored && preg_match('#[\x80-\xFF]#', $raw)) {
169  throw new ilPasswordException(
170  'The bcrypt implementation used by PHP can contain a security flaw ' .
171  'using passwords with 8-bit characters. ' .
172  'We suggest to upgrade to PHP 5.3.7+ or use passwords with only 7-bit characters.'
173  );
174  }
175  }
176 
177  $saltedPassword = crypt($hashedPassword, $prefix . $this->getCosts() . '$' . $salt);
178  if (strlen($saltedPassword) <= 13) {
179  throw new ilPasswordException('Error during the bcrypt generation');
180  }
181 
182  return $saltedPassword;
183  }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ encodePassword()

ilBcryptPasswordEncoder::encodePassword ( string  $raw,
string  $salt 
)

Encodes the raw password.

Parameters
string$rawThe password to encode
string$saltThe salt
Returns
string The encoded password

Implements ilPasswordEncoder.

Definition at line 107 of file class.ilBcryptPasswordEncoder.php.

References encode(), and ilBasePasswordEncoder\isPasswordTooLong().

Referenced by ilBcryptPasswordEncoderTest\testExceptionIsRaisedIfThePasswordExceedsTheSupportedLengthOnEncoding(), and ilBcryptPasswordEncoderTest\testPasswordShouldBeCorrectlyEncodedAndVerified().

107  : string
108  {
109  if (!$this->client_salt) {
110  throw new ilPasswordException('Missing client salt.');
111  }
112 
113  if ($this->isPasswordTooLong($raw)) {
114  throw new ilPasswordException('Invalid password.');
115  }
116 
117  return $this->encode($raw, $salt);
118  }
encode(string $raw, string $userSecret)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateClientSalt()

ilBcryptPasswordEncoder::generateClientSalt ( )
private

Definition at line 215 of file class.ilBcryptPasswordEncoder.php.

References ilPasswordUtils\getBytes(), and setClientSalt().

Referenced by readClientSalt().

215  : void
216  {
217  $this->setClientSalt(
218  substr(str_replace('+', '.', base64_encode(ilPasswordUtils::getBytes(self::MIN_SALT_SIZE))), 0, 22)
219  );
220  }
static getBytes(int $length)
Generate random bytes using OpenSSL or Mcrypt and mt_rand() as fallback.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getClientSalt()

ilBcryptPasswordEncoder::getClientSalt ( )

Definition at line 97 of file class.ilBcryptPasswordEncoder.php.

References $client_salt.

97  : ?string
98  {
99  return $this->client_salt;
100  }

◆ getClientSaltLocation()

ilBcryptPasswordEncoder::getClientSaltLocation ( )

Definition at line 197 of file class.ilBcryptPasswordEncoder.php.

Referenced by readClientSalt(), and storeClientSalt().

197  : string
198  {
199  return $this->data_directory . '/' . self::SALT_STORAGE_FILENAME;
200  }
+ Here is the caller graph for this function:

◆ getDataDirectory()

ilBcryptPasswordEncoder::getDataDirectory ( )

Definition at line 64 of file class.ilBcryptPasswordEncoder.php.

References $data_directory.

64  : string
65  {
66  return $this->data_directory;
67  }

◆ getName()

ilBcryptPasswordEncoder::getName ( )

Returns a unique name/id of the concrete password encoder.

Implements ilPasswordEncoder.

Definition at line 129 of file class.ilBcryptPasswordEncoder.php.

Referenced by ilBcryptPasswordEncoderTest\testNameShouldBeBcrypt().

129  : string
130  {
131  return 'bcrypt';
132  }
+ Here is the caller graph for this function:

◆ isBackwardCompatibilityEnabled()

ilBcryptPasswordEncoder::isBackwardCompatibilityEnabled ( )

Definition at line 74 of file class.ilBcryptPasswordEncoder.php.

References $backward_compatibility.

74  : bool
75  {
77  }

◆ isBcryptSupported()

ilBcryptPasswordEncoder::isBcryptSupported ( )
private

Definition at line 59 of file class.ilBcryptPasswordEncoder.php.

Referenced by encode().

59  : bool
60  {
61  return PHP_VERSION_ID >= 50307;
62  }
+ Here is the caller graph for this function:

◆ isPasswordValid()

ilBcryptPasswordEncoder::isPasswordValid ( string  $encoded,
string  $raw,
string  $salt 
)

Checks a raw password against an encoded password.

The raw password has to be injected into the encoder instance before.

Parameters
string$encodedAn encoded password
string$rawA raw password
string$saltThe salt, may be empty
Returns
Boolean true if the password is valid, false otherwise

Implements ilPasswordEncoder.

Definition at line 120 of file class.ilBcryptPasswordEncoder.php.

References check(), and ilBasePasswordEncoder\isPasswordTooLong().

Referenced by ilBcryptPasswordEncoderTest\testPasswordShouldBeCorrectlyEncodedAndVerified(), and ilBcryptPasswordEncoderTest\testPasswordVerificationShouldFailIfTheRawPasswordExceedsTheSupportedLength().

120  : bool
121  {
122  if (!$this->client_salt) {
123  throw new ilPasswordException('Missing client salt.');
124  }
125 
126  return !$this->isPasswordTooLong($raw) && $this->check($encoded, $raw, $salt);
127  }
check(string $encoded, string $raw, string $salt)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ isSecurityFlawIgnored()

ilBcryptPasswordEncoder::isSecurityFlawIgnored ( )

Definition at line 87 of file class.ilBcryptPasswordEncoder.php.

References $is_security_flaw_ignored.

87  : bool
88  {
90  }

◆ readClientSalt()

ilBcryptPasswordEncoder::readClientSalt ( )
private

Definition at line 202 of file class.ilBcryptPasswordEncoder.php.

References generateClientSalt(), getClientSaltLocation(), setClientSalt(), and storeClientSalt().

Referenced by __construct().

202  : void
203  {
204  if (is_file($this->getClientSaltLocation()) && is_readable($this->getClientSaltLocation())) {
205  $contents = file_get_contents($this->getClientSaltLocation());
206  if ($contents !== false && trim($contents) !== '') {
207  $this->setClientSalt($contents);
208  }
209  } else {
210  $this->generateClientSalt();
211  $this->storeClientSalt();
212  }
213  }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ requiresReencoding()

ilBcryptPasswordEncoder::requiresReencoding ( string  $encoded)

Returns whether the encoded password needs to be re-encoded.

Implements ilPasswordEncoder.

Definition at line 139 of file class.ilBcryptPasswordEncoder.php.

Referenced by ilBcryptPasswordEncoderTest\testEncoderDoesNotSupportReencoding().

139  : bool
140  {
141  return false;
142  }
+ Here is the caller graph for this function:

◆ requiresSalt()

ilBcryptPasswordEncoder::requiresSalt ( )

Returns whether the encoder requires a salt.

Implements ilPasswordEncoder.

Definition at line 134 of file class.ilBcryptPasswordEncoder.php.

Referenced by ilBcryptPasswordEncoderTest\testEncoderReliesOnSalts().

134  : bool
135  {
136  return true;
137  }
+ Here is the caller graph for this function:

◆ setBackwardCompatibility()

ilBcryptPasswordEncoder::setBackwardCompatibility ( bool  $backward_compatibility)

Set the backward compatibility $2a$ instead of $2y$ for PHP 5.3.7+.

Definition at line 82 of file class.ilBcryptPasswordEncoder.php.

References $backward_compatibility.

82  : void
83  {
84  $this->backward_compatibility = $backward_compatibility;
85  }

◆ setClientSalt()

ilBcryptPasswordEncoder::setClientSalt ( ?string  $client_salt)

Definition at line 102 of file class.ilBcryptPasswordEncoder.php.

References $client_salt.

Referenced by generateClientSalt(), and readClientSalt().

102  : void
103  {
104  $this->client_salt = $client_salt;
105  }
+ Here is the caller graph for this function:

◆ setDataDirectory()

ilBcryptPasswordEncoder::setDataDirectory ( string  $data_directory)

Definition at line 69 of file class.ilBcryptPasswordEncoder.php.

References $data_directory.

Referenced by __construct().

69  : void
70  {
71  $this->data_directory = $data_directory;
72  }
+ Here is the caller graph for this function:

◆ setIsSecurityFlawIgnored()

ilBcryptPasswordEncoder::setIsSecurityFlawIgnored ( bool  $is_security_flaw_ignored)

Definition at line 92 of file class.ilBcryptPasswordEncoder.php.

References $is_security_flaw_ignored.

Referenced by __construct().

92  : void
93  {
94  $this->is_security_flaw_ignored = $is_security_flaw_ignored;
95  }
+ Here is the caller graph for this function:

◆ storeClientSalt()

ilBcryptPasswordEncoder::storeClientSalt ( )
private

Definition at line 222 of file class.ilBcryptPasswordEncoder.php.

References Vendor\Package\$e, $location, $message, and getClientSaltLocation().

Referenced by readClientSalt().

222  : void
223  {
224  $location = $this->getClientSaltLocation();
225 
226  set_error_handler(static function (int $severity, string $message, string $file, int $line): never {
227  throw new ErrorException($message, $severity, $severity, $file, $line);
228  });
229 
230  try {
231  $result = file_put_contents($location, $this->client_salt);
232  if (!$result) {
233  throw new ilPasswordException(sprintf(
234  'Could not store the client salt in: %s. Please contact an administrator.',
235  $location
236  ));
237  }
238  } catch (Exception $e) {
239  throw new ilPasswordException(sprintf(
240  'Could not store the client salt in: %s. Please contact an administrator.',
241  $location
242  ), $e->getCode(), $e);
243  } finally {
244  restore_error_handler();
245  }
246  }
$location
Definition: buildRTE.php:22
$message
Definition: xapiexit.php:31
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Field Documentation

◆ $backward_compatibility

bool ilBcryptPasswordEncoder::$backward_compatibility = false
private

◆ $client_salt

string ilBcryptPasswordEncoder::$client_salt = null
private

Definition at line 35 of file class.ilBcryptPasswordEncoder.php.

Referenced by encode(), getClientSalt(), and setClientSalt().

◆ $data_directory

string ilBcryptPasswordEncoder::$data_directory = ''
private

Definition at line 38 of file class.ilBcryptPasswordEncoder.php.

Referenced by getDataDirectory(), and setDataDirectory().

◆ $is_security_flaw_ignored

bool ilBcryptPasswordEncoder::$is_security_flaw_ignored = false
private

◆ MIN_SALT_SIZE

const ilBcryptPasswordEncoder::MIN_SALT_SIZE = 16
private

Definition at line 30 of file class.ilBcryptPasswordEncoder.php.

◆ SALT_STORAGE_FILENAME

const ilBcryptPasswordEncoder::SALT_STORAGE_FILENAME = 'pwsalt.txt'

The documentation for this class was generated from the following file: