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
4require_once 'Services/Password/classes/encoders/class.ilBcryptPasswordEncoder.php';
5require_once 'Services/Password/test/ilPasswordBaseTest.php';
6
7use org\bovigo\vfs;
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 {
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
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
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}
An exception for terminatinating execution or to throw for unit testing.
testPasswordVerificationShouldFailIfTheRawPasswordExceedsTheSupportedLength(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated
testPasswordShouldBeCorrectlyEncodedAndVerified(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated
testCostsCanBeRetrievedWhenCostsAreSet(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated
testCostsCannotBeSetBelowRange(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated @expectedException ilPasswordException
testCostsCanBeSetInRange($costs, ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated @dataProvider costsProvider
testExceptionIsRaisedIfSaltIsMissingIsOnEncoding()
@expectedException ilPasswordException
testExceptionIsRaisedIfTheRawPasswordContainsA8BitCharacterAndBackwardCompatibilityIsEnabled()
@expectedException ilPasswordException
testExceptionIsRaisedIfSaltIsMissingIsOnVerification()
@expectedException ilPasswordException
testExceptionIsNotRaisedIfTheRawPasswordContainsA8BitCharacterAndBackwardCompatibilityIsEnabledWithIgnoredSecurityFlaw()
testEncoderReliesOnSalts(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated
testExceptionIsRaisedIfThePasswordExceedsTheSupportedLengthOnEncoding(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated @expectedException ilPasswordException
testEncoderDoesNotSupportReencoding(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated
testCostsCannotBeSetAboveRange(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated @expectedException ilPasswordException
testNameShouldBeBcrypt(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated
testExceptionIsRaisedWhenClientSaltCouldNotBeGeneratedInCaseNoClientSaltExistsYet()
@expectedException ilPasswordException
encodePassword($raw, $salt)
{{Encodes the raw password.string The encoded password}}
requiresReencoding($encoded)
{{{Returns whether or not the a encoded password needs to be re-encoded.boolean}}}
isPasswordValid($encoded, $raw, $salt)
{{Checks a raw password against an encoded password.The raw password has to be injected into the enco...
requiresSalt()
{{Returns whether or not the encoder requires a salt.boolean}}
assertException($exception_class)
defined( 'APPLICATION_ENV')||define( 'APPLICATION_ENV'
Definition: bootstrap.php:27