ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
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...
 
 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...
 
 isSupportedByRuntime ()
 Returns whether the encoder is supported by the runtime (PHP, HHVM, ...) More...
 

Data Fields

const string 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 int 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

Reimplemented from ilBcryptPhpPasswordEncoder.

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

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 }
setDataDirectory(string $data_directory)
setIsSecurityFlawIgnored(bool $is_security_flaw_ignored)
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc

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

+ 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.

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.

References ilBasePasswordEncoder\comparePasswords().

Referenced by isPasswordValid().

+ 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.

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 }
Class for user password exception handling in ILIAS.

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

Referenced by encodePassword().

+ 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

Reimplemented from ilBcryptPhpPasswordEncoder.

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

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)

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

Referenced by ilBcryptPasswordEncoderTest\testBackwardCompatibility(), ilBcryptPasswordEncoderTest\testExceptionIfPasswordsContainA8BitCharacterAndBackwardCompatibilityIsEnabled(), ilBcryptPasswordEncoderTest\testExceptionIsRaisedIfSaltIsMissingIsOnEncoding(), and ilBcryptPasswordEncoderTest\testNoExceptionIfPasswordsContainA8BitCharacterAndBackwardCompatibilityIsEnabledWithIgnoredSecurityFlaw().

+ 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.

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.

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

Referenced by readClientSalt().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getClientSalt()

ilBcryptPasswordEncoder::getClientSalt ( )

◆ getClientSaltLocation()

ilBcryptPasswordEncoder::getClientSaltLocation ( )

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

197 : string
198 {
199 return $this->data_directory . '/' . self::SALT_STORAGE_FILENAME;
200 }

References SALT_STORAGE_FILENAME.

Referenced by readClientSalt(), and storeClientSalt().

+ Here is the caller graph for this function:

◆ getDataDirectory()

ilBcryptPasswordEncoder::getDataDirectory ( )

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

64 : string
65 {
67 }

References $data_directory.

◆ getName()

ilBcryptPasswordEncoder::getName ( )

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

Reimplemented from ilBcryptPhpPasswordEncoder.

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

129 : string
130 {
131 return 'bcrypt';
132 }

Referenced by ilBcryptPasswordEncoderTest\testNameShouldBeBcrypt().

+ Here is the caller graph for this function:

◆ isBackwardCompatibilityEnabled()

ilBcryptPasswordEncoder::isBackwardCompatibilityEnabled ( )

◆ isBcryptSupported()

ilBcryptPasswordEncoder::isBcryptSupported ( )
private

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

59 : bool
60 {
61 return PHP_VERSION_ID >= 50307;
62 }

Referenced by encode().

+ 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

Reimplemented from ilBcryptPhpPasswordEncoder.

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

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)

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

Referenced by ilBcryptPasswordEncoderTest\testBackwardCompatibility(), and ilBcryptPasswordEncoderTest\testExceptionIsRaisedIfSaltIsMissingIsOnVerification().

+ 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.

◆ readClientSalt()

ilBcryptPasswordEncoder::readClientSalt ( )
private

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

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 }

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

Referenced by __construct().

+ 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.

Reimplemented from ilBcryptPhpPasswordEncoder.

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

139 : bool
140 {
141 return false;
142 }

Referenced by ilBcryptPasswordEncoderTest\testEncoderDoesNotSupportReencoding().

+ Here is the caller graph for this function:

◆ requiresSalt()

ilBcryptPasswordEncoder::requiresSalt ( )

Returns whether the encoder requires a salt.

Reimplemented from ilBasePasswordEncoder.

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

134 : bool
135 {
136 return true;
137 }

Referenced by ilBcryptPasswordEncoderTest\testEncoderReliesOnSalts().

+ Here is the caller graph for this function:

◆ setBackwardCompatibility()

ilBcryptPasswordEncoder::setBackwardCompatibility ( bool  $backward_compatibility)

◆ setClientSalt()

◆ setDataDirectory()

ilBcryptPasswordEncoder::setDataDirectory ( string  $data_directory)

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

69 : void
70 {
71 $this->data_directory = $data_directory;
72 }

References $data_directory.

Referenced by __construct().

+ 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.

92 : void
93 {
94 $this->is_security_flaw_ignored = $is_security_flaw_ignored;
95 }

References $is_security_flaw_ignored.

Referenced by __construct(), and ilBcryptPasswordEncoderTest\testNoExceptionIfPasswordsContainA8BitCharacterAndBackwardCompatibilityIsEnabledWithIgnoredSecurityFlaw().

+ Here is the caller graph for this function:

◆ storeClientSalt()

ilBcryptPasswordEncoder::storeClientSalt ( )
private

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

222 : void
223 {
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.',
236 ));
237 }
238 } catch (Exception $e) {
239 throw new ilPasswordException(sprintf(
240 'Could not store the client salt in: %s. Please contact an administrator.',
242 ), $e->getCode(), $e);
243 } finally {
244 restore_error_handler();
245 }
246 }
$location
Definition: buildRTE.php:22
$message
Definition: xapiexit.php:31

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

Referenced by readClientSalt().

+ 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 int ilBcryptPasswordEncoder::MIN_SALT_SIZE = 16
private

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

◆ SALT_STORAGE_FILENAME

const string ilBcryptPasswordEncoder::SALT_STORAGE_FILENAME = 'pwsalt.txt'

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