19declare(strict_types=1);
70 return class_exists(
'org\bovigo\vfs\vfsStreamWrapper');
76 $this->markTestSkipped(
'Skipped test, vfsStream (https://github.com/bovigo/vfsStream) required');
78 vfs\vfsStream::setup();
79 $this->
setTestDirectory(vfs\vfsStream::newDirectory(
'tests')->at(vfs\vfsStreamWrapper::getRoot()));
90 for (
$i = 4;
$i <= 31; ++
$i) {
91 $data[sprintf(
'Costs: %s',
$i)] = [(string)
$i];
109 'ignore_security_flaw' =>
true,
112 $this->assertTrue($security_flaw_ignoring_encoder->isSecurityFlawIgnored());
115 'ignore_security_flaw' =>
false,
118 $this->assertFalse($security_flaw_respecting_encoder->isSecurityFlawIgnored());
121 'cost' => self::VALID_COSTS,
124 $this->assertInstanceOf(ilBcryptPasswordEncoder::class, $encoder);
125 $this->assertSame(self::VALID_COSTS, $encoder->getCosts());
126 $this->assertFalse($encoder->isSecurityFlawIgnored());
127 $encoder->setClientSalt(self::CLIENT_SALT);
141 $this->assertSame($expected, $encoder->
getCosts());
150 $this->expectException(ilPasswordException::class);
160 $this->expectException(ilPasswordException::class);
183 $encoded_password = $encoder->
encodePassword(self::PASSWORD, self::PASSWORD_SALT);
184 $this->assertTrue($encoder->
isPasswordValid($encoded_password, self::PASSWORD, self::PASSWORD_SALT));
185 $this->assertFalse($encoder->
isPasswordValid($encoded_password, self::WRONG_PASSWORD, self::PASSWORD_SALT));
198 $encoder->
setCosts(self::VALID_COSTS);
199 $encoder->
encodePassword(str_repeat(
'a', 5000), self::PASSWORD_SALT);
209 $encoder->setCosts(self::VALID_COSTS);
210 $this->assertFalse($encoder->
isPasswordValid(
'encoded', str_repeat(
'a', 5000), self::PASSWORD_SALT));
234 $this->assertSame(
'bcrypt', $encoder->
getName());
239 $this->skipIfvfsStreamNotSupported();
241 $this->expectException(ilPasswordException::class);
242 $encoder = $this->getInstanceWithConfiguredDataDirectory();
244 $encoder->
setCosts(self::VALID_COSTS);
250 $this->skipIfvfsStreamNotSupported();
252 $this->expectException(ilPasswordException::class);
253 $encoder = $this->getInstanceWithConfiguredDataDirectory();
255 $encoder->
setCosts(self::VALID_COSTS);
256 $encoder->
isPasswordValid(
'12121212', self::PASSWORD, self::PASSWORD_SALT);
261 $this->skipIfvfsStreamNotSupported();
263 $this->getTestDirectory()->chmod(0777);
266 $encoder = $this->getInstanceWithConfiguredDataDirectory();
267 $this->assertSame(self::CLIENT_SALT, $encoder->
getClientSalt());
272 $this->skipIfvfsStreamNotSupported();
274 $this->getTestDirectory()->chmod(0777);
276 $encoder = $this->getInstanceWithConfiguredDataDirectory();
282 $this->skipIfvfsStreamNotSupported();
284 $this->expectException(ilPasswordException::class);
285 $this->getTestDirectory()->chmod(0000);
287 $this->getInstanceWithConfiguredDataDirectory();
292 $this->skipIfvfsStreamNotSupported();
294 $encoder = $this->getInstanceWithConfiguredDataDirectory();
303 $this->skipIfvfsStreamNotSupported();
305 $encoder = $this->getInstanceWithConfiguredDataDirectory();
309 $encoded_password = $encoder->
encodePassword(self::PASSWORD, self::PASSWORD_SALT);
310 $this->assertTrue($encoder->
isPasswordValid($encoded_password, self::PASSWORD, self::PASSWORD_SALT));
311 $this->assertSame(
'$2a$', substr($encoded_password, 0, 4));
313 $another_encoder = $this->getInstanceWithConfiguredDataDirectory();
314 $another_encoder->setClientSalt(self::CLIENT_SALT);
316 $another_encoder->setBackwardCompatibility(
false);
317 $another_encoded_password = $another_encoder->encodePassword(self::PASSWORD, self::PASSWORD_SALT);
318 $this->assertSame(
'$2y$', substr($another_encoded_password, 0, 4));
319 $this->assertTrue($another_encoder->isPasswordValid($encoded_password, self::PASSWORD, self::PASSWORD_SALT));
324 $this->skipIfvfsStreamNotSupported();
326 $this->expectException(ilPasswordException::class);
327 $encoder = $this->getInstanceWithConfiguredDataDirectory();
330 $encoder->
encodePassword(self::PASSWORD . chr(195), self::PASSWORD_SALT);
339 $this->skipIfvfsStreamNotSupported();
341 $encoder = $this->getInstanceWithConfiguredDataDirectory();
345 $encoder->
encodePassword(self::PASSWORD . chr(195), self::PASSWORD_SALT);
testClientSaltIsGeneratedWhenNoClientSaltExistsYet()
testCostsCanBeSetInRange(string $costs, ilBcryptPasswordEncoder $encoder)
@doesNotPerformAssertions @depends testInstanceCanBeCreated @dataProvider costsProvider
testInstanceCanBeCreatedAndInitializedWithClientSalt()
testPasswordVerificationShouldFailIfTheRawPasswordExceedsTheSupportedLength(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated
setTestDirectory(vfs\vfsStreamDirectory $testDirectory)
getInstanceWithConfiguredDataDirectory()
testPasswordShouldBeCorrectlyEncodedAndVerified(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated
testCostsCanBeRetrievedWhenCostsAreSet(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated
testBackwardCompatibilityCanBeRetrievedWhenBackwardCompatibilityIsSet()
testCostsCannotBeSetBelowRange(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated
testExceptionIfPasswordsContainA8BitCharacterAndBackwardCompatibilityIsEnabled()
testNoExceptionIfPasswordsContainA8BitCharacterAndBackwardCompatibilityIsEnabledWithIgnoredSecurityFlaw()
@doesNotPerformAssertions
vfs vfsStreamDirectory $testDirectory
setTestDirectoryUrl(string $testDirectoryUrl)
testExceptionIsRaisedIfSaltIsMissingIsOnEncoding()
testInstanceCanBeCreated()
testExceptionIsRaisedIfSaltIsMissingIsOnVerification()
testEncoderReliesOnSalts(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated
testExceptionIsRaisedIfThePasswordExceedsTheSupportedLengthOnEncoding(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated
testBackwardCompatibility()
testEncoderDoesNotSupportReencoding(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated
testCostsCannotBeSetAboveRange(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated
skipIfvfsStreamNotSupported()
testNameShouldBeBcrypt(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated
testExceptionIsRaisedWhenClientSaltCouldNotBeGeneratedInCaseNoClientSaltExistsYet()
encodePassword(string $raw, string $salt)
Encodes the raw password.
getName()
Returns a unique name/id of the concrete password encoder.
setBackwardCompatibility(bool $backward_compatibility)
Set the backward compatibility $2a$ instead of $2y$ for PHP 5.3.7+.
const SALT_STORAGE_FILENAME
isBackwardCompatibilityEnabled()
requiresSalt()
Returns whether the encoder requires a salt.
isPasswordValid(string $encoded, string $raw, string $salt)
Checks a raw password against an encoded password.
setClientSalt(?string $client_salt)
requiresReencoding(string $encoded)
Returns whether the encoded password needs to be re-encoded.
setIsSecurityFlawIgnored(bool $is_security_flaw_ignored)
Class for user password exception handling in ILIAS.