ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
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 
12 {
16  const VALID_COSTS = '08';
17 
21  const PASSWORD = 'password';
22 
26  const WRONG_PASSWORD = 'wrong_password';
27 
31  const CLIENT_SALT = 'homer!12345_/';
32 
36  const PASSWORD_SALT = 'salt';
37 
41  protected $test_directory;
42 
46  public function getTestDirectory()
47  {
48  return $this->test_directory;
49  }
50 
55  {
56  $this->test_directory = $test_directory;
57  }
58 
62  private function isVsfStreamInstalled()
63  {
64  return @include_once('vfsStream.php');
65  }
66 
70  protected function setUp()
71  {
72  if($this->isVsfStreamInstalled())
73  {
74  vfsStream::setup();
75  $this->setTestDirectory(vfsStream::newDirectory('tests')->at(vfsStreamWrapper::getRoot()));
76  if(!defined('CLIENT_DATA_DIR'))
77  {
78  define('CLIENT_DATA_DIR', vfsStream::url('root/tests'));
79  }
80  }
81  else if(!defined('CLIENT_DATA_DIR'))
82  {
83  define('CLIENT_DATA_DIR', '/tmp');
84  }
85 
86  parent::setUp();
87  }
88 
92  public function testInstanceCanBeCreated()
93  {
94  $security_flaw_ignoring_encoder = new ilBcryptPasswordEncoder(array(
95  'ignore_security_flaw' => true
96  ));
97  $this->assertTrue($security_flaw_ignoring_encoder->isSecurityFlawIgnored());
98 
99  $security_flaw_respecting_encoder = new ilBcryptPasswordEncoder(array(
100  'ignore_security_flaw' => false
101  ));
102  $this->assertFalse($security_flaw_respecting_encoder->isSecurityFlawIgnored());
103 
104  $encoder = new ilBcryptPasswordEncoder(array(
105  'cost' => self::VALID_COSTS
106  ));
107  $this->assertInstanceOf('ilBcryptPasswordEncoder', $encoder);
108  $this->assertEquals(self::VALID_COSTS, $encoder->getCosts());
109  $this->assertFalse($encoder->isSecurityFlawIgnored());
110  $encoder->setClientSalt(self::CLIENT_SALT);
111  return $encoder;
112  }
113 
118  {
119  $encoder->setCosts(4);
120  $this->assertEquals(4, $encoder->getCosts());
121  }
122 
128  {
129  $encoder->setCosts(32);
130  }
131 
137  {
138  $encoder->setCosts(3);
139  }
140 
145  public function testCostsCanBeSetInRange($costs, ilBcryptPasswordEncoder $encoder)
146  {
147  $encoder->setCosts($costs);
148  }
149 
153  public function costsProvider()
154  {
155  $data = array();
156  for($i = 4; $i <= 31; $i++)
157  {
158  $data[] = array($i);
159  }
160  return $data;
161  }
162 
167  {
168  $encoder->setCosts(self::VALID_COSTS);
169  $encoded_password = $encoder->encodePassword(self::PASSWORD, self::PASSWORD_SALT);
170  $this->assertTrue($encoder->isPasswordValid($encoded_password, self::PASSWORD, self::PASSWORD_SALT));
171  $this->assertFalse($encoder->isPasswordValid($encoded_password, self::WRONG_PASSWORD, self::PASSWORD_SALT));
172  return $encoder;
173  }
174 
180  {
181  $encoder->setCosts(self::VALID_COSTS);
182  $encoder->encodePassword(str_repeat('a', 5000), self::PASSWORD_SALT);
183  }
184 
189  {
190  $encoder->setCosts(self::VALID_COSTS);
191  $this->assertFalse($encoder->isPasswordValid('encoded', str_repeat('a', 5000), self::PASSWORD_SALT));
192  }
193 
198  {
199  $encoder = new ilBcryptPasswordEncoder();
200  $encoder->setClientSalt(null);
201  $encoder->setCosts(self::VALID_COSTS);
202  $encoder->encodePassword(self::PASSWORD, self::PASSWORD_SALT);
203  }
204 
209  {
210  $encoder = new ilBcryptPasswordEncoder();
211  $encoder->setClientSalt(null);
212  $encoder->setCosts(self::VALID_COSTS);
213  $encoder->isPasswordValid('12121212', self::PASSWORD, self::PASSWORD_SALT);
214  }
215 
220  {
222 
223  $this->getTestDirectory()->chmod(0777);
224  vfsStream::newFile(ilBcryptPasswordEncoder::SALT_STORAGE_FILENAME)->withContent(self::CLIENT_SALT)->at($this->getTestDirectory());
225 
226  $encoder = new ilBcryptPasswordEncoder();
227  $this->assertEquals(self::CLIENT_SALT, $encoder->getClientSalt());
228  }
229 
234  {
235  $encoder = new ilBcryptPasswordEncoder();
236  $encoder->setBackwardCompatibility(true);
237  $this->assertTrue($encoder->isBackwardCompatibilityEnabled());
238  $encoder->setBackwardCompatibility(false);
239  $this->assertFalse($encoder->isBackwardCompatibilityEnabled());
240  }
241 
245  public function testBackwardCompatibility()
246  {
248 
249  $encoder = new ilBcryptPasswordEncoder();
250  $encoder->setClientSalt(self::CLIENT_SALT);
251  $encoder->setBackwardCompatibility(true);
252  $encoded_password = $encoder->encodePassword(self::PASSWORD, self::PASSWORD_SALT);
253  $this->assertTrue($encoder->isPasswordValid($encoded_password, self::PASSWORD, self::PASSWORD_SALT));
254  $this->assertEquals('$2a$', substr($encoded_password, 0, 4));
255 
256  $another_encoder = new ilBcryptPasswordEncoder();
257  $another_encoder->setClientSalt(self::CLIENT_SALT);
258  $another_encoder->setBackwardCompatibility(false);
259  $another_encoded_password = $another_encoder->encodePassword(self::PASSWORD, self::PASSWORD_SALT);
260  $this->assertEquals('$2y$', substr($another_encoded_password, 0, 4));
261  $this->assertTrue($another_encoder->isPasswordValid($encoded_password, self::PASSWORD, self::PASSWORD_SALT));
262  }
263 
268  {
269  if(version_compare(phpversion(), '5.3.7', '<'))
270  {
271  $this->markTestSkipped('Requires PHP >= 5.3.7');
272  }
273  }
274 
278  private function skipIfvfsStreamNotSupported()
279  {
280  if(!$this->isVsfStreamInstalled())
281  {
282  $this->markTestSkipped('Requires vfsStream (http://vfs.bovigo.org)');
283  }
284  }
285 
290  {
291  $encoder = new ilBcryptPasswordEncoder();
292  $encoder->setClientSalt(self::CLIENT_SALT);
293  $encoder->setBackwardCompatibility(true);
294  $encoder->encodePassword(self::PASSWORD . chr(195), self::PASSWORD_SALT);
295  }
296 
301  {
302  $encoder = new ilBcryptPasswordEncoder();
303  $encoder->setClientSalt(self::CLIENT_SALT);
304  $encoder->setBackwardCompatibility(true);
305  $encoder->setIsSecurityFlawIgnored(true);
306  $encoder->encodePassword(self::PASSWORD . chr(195), self::PASSWORD_SALT);
307  }
308 
312  public function testNameShouldBeBcrypt()
313  {
314  $encoder = new ilBcryptPasswordEncoder();
315  $this->assertEquals('bcrypt', $encoder->getName());
316  }
317 }
testCostsCannotBeSetAboveRange(ilBcryptPasswordEncoder $encoder)
testInstanceCanBeCreated ilPasswordException
encodePassword($raw, $salt)
{Encodes the raw password.The password to encode The salt string The encoded password} ...
testCostsCanBeRetrievedWhenCostsAreSet(ilBcryptPasswordEncoder $encoder)
testInstanceCanBeCreated
testCostsCanBeSetInRange($costs, ilBcryptPasswordEncoder $encoder)
testInstanceCanBeCreated costsProvider
testExceptionIsNotRaisedIfTheRawPasswordContainsA8BitCharacterAndBackwardCompatibilityIsEnabledWithIgnoredSecurityFlaw()
$data
testPasswordShouldBeCorrectlyEncodedAndVerified(ilBcryptPasswordEncoder $encoder)
testInstanceCanBeCreated
testExceptionIsRaisedIfSaltIsMissingIsOnEncoding()
ilPasswordException
testExceptionIsRaisedIfThePasswordExceedsTheSupportedLengthOnEncoding(ilBcryptPasswordEncoder $encoder)
testInstanceCanBeCreated ilPasswordException
testExceptionIsRaisedIfSaltIsMissingIsOnVerification()
ilPasswordException
testPasswordVerificationShouldFailIfTheRawPasswordExceedsTheSupportedLength(ilBcryptPasswordEncoder $encoder)
testInstanceCanBeCreated
testExceptionIsRaisedIfTheRawPasswordContainsA8BitCharacterAndBackwardCompatibilityIsEnabled()
ilPasswordException
testCostsCannotBeSetBelowRange(ilBcryptPasswordEncoder $encoder)
testInstanceCanBeCreated ilPasswordException
isPasswordValid($encoded, $raw, $salt)
{Checks a raw password against an encoded password.The raw password has to be injected into the encod...