This repository has been archived by the owner on Aug 12, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
PasswordLockTest.php
138 lines (105 loc) · 3.85 KB
/
PasswordLockTest.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
<?php
declare(strict_types=1);
namespace TypistTech\WPPasswordArgonTwo;
use Codeception\TestCase\WPTestCase;
class PasswordLockTest extends WPTestCase
{
private const DUMMY_PEPPER = 'dummy_pepper';
private const DUMMY_PASSWORD = 'pa5$word';
private const MD5_HASH = '5f4dcc3b5aa765d61d8327deb882cf99';
private const PHPASS_HASH = '$P$BasW5IPx2SEVGbVdiIEzx2VrRb/.eF0';
private const BCRYPT_HASH = '$2y$10$EkVBmTI0cbPvPdnTYeVk8eIt6qpHk09C8DB5iZwHbYBu5ot2PyAnq';
/** @test */
public function it_implements_validator_interface()
{
$passwordLock = new PasswordLock(self::DUMMY_PEPPER, []);
$this->assertInstanceOf(ValidatorInterface::class, $passwordLock);
}
/** @test */
public function it_extends_validator()
{
$passwordLock = new PasswordLock(self::DUMMY_PEPPER, []);
$this->assertInstanceOf(Validator::class, $passwordLock);
}
/** @test */
public function it_hashes_with_argon2i()
{
$passwordLock = new PasswordLock(self::DUMMY_PEPPER, []);
$ciphertext = $passwordLock->hash(self::DUMMY_PASSWORD);
$this->assertFalse(
password_needs_rehash($ciphertext, PASSWORD_ARGON2I, WP_PASSWORD_ARGON_TWO_OPTIONS)
);
}
/** @test */
public function it_does_not_truncate_long_password()
{
$longPassword = str_repeat('bbcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+', 110);
$passwordLock = new PasswordLock(self::DUMMY_PEPPER, []);
$isValid = $passwordLock->isValid(
substr($longPassword, 0, -1) . 'a',
$passwordLock->hash($longPassword)
);
$this->assertFalse($isValid);
}
/** @test */
public function it_hash_password_into_shorter_than_256_char_string()
{
$longPassword = str_repeat('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+', 110);
$passwordLock = new PasswordLock(self::DUMMY_PEPPER, []);
$ciphertext = $passwordLock->hash($longPassword);
$this->assertLessThan(
256,
strlen($ciphertext)
);
}
/** @test */
public function it_needs_rehash_when_options_changed()
{
$oldOptions = [
'memory_cost' => 1 << 17, // 128 Mb
'time_cost' => 2,
'threads' => 1,
];
$newOptions = array_merge($oldOptions, ['time_cost' => 3]);
$oldPasswordLock = new PasswordLock(self::DUMMY_PEPPER, $oldOptions);
$newPasswordLock = new PasswordLock(self::DUMMY_PEPPER, $newOptions);
$ciphertext = $oldPasswordLock->hash(self::DUMMY_PASSWORD);
$needsRehash = $newPasswordLock->needsRehash($ciphertext);
$this->assertTrue($needsRehash);
}
/** @test */
public function it_does_not_need_rehash_when_options_unchanged()
{
$options = [
'memory_cost' => 1 << 17, // 128 Mb
'time_cost' => 2,
'threads' => 1,
];
$oldPasswordLock = new PasswordLock(self::DUMMY_PEPPER, $options);
$newPasswordLock = new PasswordLock(self::DUMMY_PEPPER, $options);
$ciphertext = $oldPasswordLock->hash(self::DUMMY_PASSWORD);
$needsRehash = $newPasswordLock->needsRehash($ciphertext);
$this->assertFalse($needsRehash);
}
/** @test */
public function bcrypt_hash_needs_rehash()
{
$this->assertNeedsRehash(self::BCRYPT_HASH);
}
/** @test */
public function md5_hash_needs_rehash()
{
$this->assertNeedsRehash(self::MD5_HASH);
}
/** @test */
public function phpass_hash_needs_rehash()
{
$this->assertNeedsRehash(self::PHPASS_HASH);
}
private function assertNeedsRehash(string $ciphertext)
{
$passwordLock = new PasswordLock(self::DUMMY_PEPPER, []);
$needsRehash = $passwordLock->needsRehash($ciphertext);
$this->assertTrue($needsRehash);
}
}