ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
ilBcryptPasswordEncoderTest.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2014 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 require_once 'Services/Password/classes/encoders/class.ilBcryptPasswordEncoder.php';
5 require_once 'Services/Password/test/ilPasswordBaseTest.php';
6 
8 
15 {
19  const VALID_COSTS = '08';
20 
24  const PASSWORD = 'password';
25 
29  const WRONG_PASSWORD = 'wrong_password';
30 
34  const CLIENT_SALT = 'homer!12345_/';
35 
39  const PASSWORD_SALT = 'salt';
40 
44  protected $test_directory;
45 
49  public function getTestDirectory()
50  {
51  return $this->test_directory;
52  }
53 
58  {
59  $this->test_directory = $test_directory;
60  }
61 
65  protected function setUp()
66  {
67  vfs\vfsStream::setup();
68  $this->setTestDirectory(vfs\vfsStream::newDirectory('tests')->at(vfs\vfsStreamWrapper::getRoot()));
69 
70  if(!defined('CLIENT_DATA_DIR'))
71  {
72  define('CLIENT_DATA_DIR', vfs\vfsStream::url('root/tests'));
73  }
74 
75  parent::setUp();
76  }
77 
81  private function skipIfPhpVersionIsNotSupported()
82  {
83  if(version_compare(phpversion(), '5.3.7', '<'))
84  {
85  $this->markTestSkipped('Requires PHP >= 5.3.7');
86  }
87  }
88 
92  public function costsProvider()
93  {
94  $data = array();
95  for($i = 4; $i <= 31; $i++)
96  {
97  $data[] = array($i);
98  }
99  return $data;
100  }
101 
105  public function testInstanceCanBeCreated()
106  {
107  $security_flaw_ignoring_encoder = new ilBcryptPasswordEncoder(array(
108  'ignore_security_flaw' => true
109  ));
110  $this->assertTrue($security_flaw_ignoring_encoder->isSecurityFlawIgnored());
111 
112  $security_flaw_respecting_encoder = new ilBcryptPasswordEncoder(array(
113  'ignore_security_flaw' => false
114  ));
115  $this->assertFalse($security_flaw_respecting_encoder->isSecurityFlawIgnored());
116 
117  $encoder = new ilBcryptPasswordEncoder(array(
118  'cost' => self::VALID_COSTS
119  ));
120  $this->assertInstanceOf('ilBcryptPasswordEncoder', $encoder);
121  $this->assertEquals(self::VALID_COSTS, $encoder->getCosts());
122  $this->assertFalse($encoder->isSecurityFlawIgnored());
123  $encoder->setClientSalt(self::CLIENT_SALT);
124  return $encoder;
125  }
126 
131  {
132  $encoder->setCosts(4);
133  $this->assertEquals(4, $encoder->getCosts());
134  }
135 
141  {
142  $this->assertException(ilPasswordException::class);
143  $encoder->setCosts(32);
144  }
145 
151  {
152  $this->assertException(ilPasswordException::class);
153  $encoder->setCosts(3);
154  }
155 
160  public function testCostsCanBeSetInRange($costs, ilBcryptPasswordEncoder $encoder)
161  {
162  $encoder->setCosts($costs);
163  }
164 
169  {
170  $encoder->setCosts(self::VALID_COSTS);
171  $encoded_password = $encoder->encodePassword(self::PASSWORD, self::PASSWORD_SALT);
172  $this->assertTrue($encoder->isPasswordValid($encoded_password, self::PASSWORD, self::PASSWORD_SALT));
173  $this->assertFalse($encoder->isPasswordValid($encoded_password, self::WRONG_PASSWORD, self::PASSWORD_SALT));
174  return $encoder;
175  }
176 
182  {
183  $this->assertException(ilPasswordException::class);
184  $encoder->setCosts(self::VALID_COSTS);
185  $encoder->encodePassword(str_repeat('a', 5000), self::PASSWORD_SALT);
186  }
187 
192  {
193  $encoder->setCosts(self::VALID_COSTS);
194  $this->assertFalse($encoder->isPasswordValid('encoded', str_repeat('a', 5000), self::PASSWORD_SALT));
195  }
196 
201  {
202  $this->assertTrue($encoder->requiresSalt());
203  }
204 
209  {
210  $this->assertFalse($encoder->requiresReencoding('hello'));
211  }
212 
217  {
218  $this->assertEquals('bcrypt', $encoder->getName());
219  }
220 
225  {
226  $this->assertException(ilPasswordException::class);
227  $encoder = new ilBcryptPasswordEncoder();
228  $encoder->setClientSalt(null);
229  $encoder->setCosts(self::VALID_COSTS);
230  $encoder->encodePassword(self::PASSWORD, self::PASSWORD_SALT);
231  }
232 
237  {
238  $this->assertException(ilPasswordException::class);
239  $encoder = new ilBcryptPasswordEncoder();
240  $encoder->setClientSalt(null);
241  $encoder->setCosts(self::VALID_COSTS);
242  $encoder->isPasswordValid('12121212', self::PASSWORD, self::PASSWORD_SALT);
243  }
244 
249  {
250  $this->getTestDirectory()->chmod(0777);
251  vfs\vfsStream::newFile(ilBcryptPasswordEncoder::SALT_STORAGE_FILENAME)->withContent(self::CLIENT_SALT)->at($this->getTestDirectory());
252 
253  $encoder = new ilBcryptPasswordEncoder();
254  $this->assertEquals(self::CLIENT_SALT, $encoder->getClientSalt());
255  }
256 
261  {
262  $this->getTestDirectory()->chmod(0777);
263 
264  $encoder = new ilBcryptPasswordEncoder();
265  $this->assertNotNull($encoder->getClientSalt());
266  }
267 
272  {
273  $this->assertException(ilPasswordException::class);
274  $this->getTestDirectory()->chmod(0000);
275 
276  $encoder = new ilBcryptPasswordEncoder();
277  }
278 
283  {
284  $encoder = new ilBcryptPasswordEncoder();
285  $encoder->setBackwardCompatibility(true);
286  $this->assertTrue($encoder->isBackwardCompatibilityEnabled());
287  $encoder->setBackwardCompatibility(false);
288  $this->assertFalse($encoder->isBackwardCompatibilityEnabled());
289  }
290 
294  public function testBackwardCompatibility()
295  {
297 
298  $encoder = new ilBcryptPasswordEncoder();
299  $encoder->setClientSalt(self::CLIENT_SALT);
300  $encoder->setBackwardCompatibility(true);
301  $encoded_password = $encoder->encodePassword(self::PASSWORD, self::PASSWORD_SALT);
302  $this->assertTrue($encoder->isPasswordValid($encoded_password, self::PASSWORD, self::PASSWORD_SALT));
303  $this->assertEquals('$2a$', substr($encoded_password, 0, 4));
304 
305  $another_encoder = new ilBcryptPasswordEncoder();
306  $another_encoder->setClientSalt(self::CLIENT_SALT);
307  $another_encoder->setBackwardCompatibility(false);
308  $another_encoded_password = $another_encoder->encodePassword(self::PASSWORD, self::PASSWORD_SALT);
309  $this->assertEquals('$2y$', substr($another_encoded_password, 0, 4));
310  $this->assertTrue($another_encoder->isPasswordValid($encoded_password, self::PASSWORD, self::PASSWORD_SALT));
311  }
312 
317  {
318  $this->assertException(ilPasswordException::class);
319  $encoder = new ilBcryptPasswordEncoder();
320  $encoder->setClientSalt(self::CLIENT_SALT);
321  $encoder->setBackwardCompatibility(true);
322  $encoder->encodePassword(self::PASSWORD . chr(195), self::PASSWORD_SALT);
323  }
324 
329  {
330  $encoder = new ilBcryptPasswordEncoder();
331  $encoder->setClientSalt(self::CLIENT_SALT);
332  $encoder->setBackwardCompatibility(true);
333  $encoder->setIsSecurityFlawIgnored(true);
334  $encoder->encodePassword(self::PASSWORD . chr(195), self::PASSWORD_SALT);
335  }
336 }
testCostsCannotBeSetAboveRange(ilBcryptPasswordEncoder $encoder)
testInstanceCanBeCreated ilPasswordException
encodePassword($raw, $salt)
{Encodes the raw password.The password to encode The salt string The encoded password} ...
requiresSalt()
{Returns whether or not the encoder requires a salt.boolean}
testCostsCanBeRetrievedWhenCostsAreSet(ilBcryptPasswordEncoder $encoder)
testInstanceCanBeCreated
testEncoderDoesNotSupportReencoding(ilBcryptPasswordEncoder $encoder)
testInstanceCanBeCreated
testCostsCanBeSetInRange($costs, ilBcryptPasswordEncoder $encoder)
testInstanceCanBeCreated costsProvider
requiresReencoding($encoded)
{Returns whether or not the a encoded password needs to be re-encoded.string boolean} ...
testExceptionIsNotRaisedIfTheRawPasswordContainsA8BitCharacterAndBackwardCompatibilityIsEnabledWithIgnoredSecurityFlaw()
testPasswordShouldBeCorrectlyEncodedAndVerified(ilBcryptPasswordEncoder $encoder)
testInstanceCanBeCreated
testExceptionIsRaisedIfSaltIsMissingIsOnEncoding()
ilPasswordException
testExceptionIsRaisedIfThePasswordExceedsTheSupportedLengthOnEncoding(ilBcryptPasswordEncoder $encoder)
testInstanceCanBeCreated ilPasswordException
testExceptionIsRaisedIfSaltIsMissingIsOnVerification()
ilPasswordException
testPasswordVerificationShouldFailIfTheRawPasswordExceedsTheSupportedLength(ilBcryptPasswordEncoder $encoder)
testInstanceCanBeCreated
Create styles array
The data for the language used.
getName()
{Returns a unique name/id of the concrete password encoder.string}
testExceptionIsRaisedIfTheRawPasswordContainsA8BitCharacterAndBackwardCompatibilityIsEnabled()
ilPasswordException
testExceptionIsRaisedWhenClientSaltCouldNotBeGeneratedInCaseNoClientSaltExistsYet()
ilPasswordException
testCostsCannotBeSetBelowRange(ilBcryptPasswordEncoder $encoder)
testInstanceCanBeCreated ilPasswordException
testNameShouldBeBcrypt(ilBcryptPasswordEncoder $encoder)
testInstanceCanBeCreated
testEncoderReliesOnSalts(ilBcryptPasswordEncoder $encoder)
testInstanceCanBeCreated
isPasswordValid($encoded, $raw, $salt)
{Checks a raw password against an encoded password.The raw password has to be injected into the encod...
defined( 'APPLICATION_ENV')||define( 'APPLICATION_ENV'
Definition: bootstrap.php:27
assertException($exception_class)