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
4require_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 {
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
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
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}
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()
testExceptionIsRaisedIfThePasswordExceedsTheSupportedLengthOnEncoding(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated @expectedException ilPasswordException
testCostsCannotBeSetAboveRange(ilBcryptPasswordEncoder $encoder)
@depends testInstanceCanBeCreated @expectedException ilPasswordException
encodePassword($raw, $salt)
{Encodes the raw password.string The encoded password}
isPasswordValid($encoded, $raw, $salt)
{Checks a raw password against an encoded password.The raw password has to be injected into the encod...
$data