Completed
Pull Request — master (#5741)
by Damian
12:40
created

PasswordEncryptorTest   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 165
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 4

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 165
rs 10
wmc 13
lcom 2
cbo 4

11 Methods

Rating   Name   Duplication   Size   Complexity  
A setUp() 0 4 1
A tearDown() 0 5 1
A testCreateForCode() 0 9 1
A testCreateForCodeNotFound() 0 3 1
A testRegister() 0 11 1
A testUnregister() 0 9 1
A testEncryptorPHPHashWithArguments() 0 9 1
A testEncryptorPHPHash() 0 14 1
A testEncryptorBlowfish() 0 48 3
A testEncryptorPHPHashCheck() 0 10 1
A testEncryptorLegacyPHPHashCheck() 0 15 1
1
<?php
2
3
use SilverStripe\Security\PasswordEncryptor_Blowfish;
4
use SilverStripe\Security\PasswordEncryptor;
5
6
class PasswordEncryptorTest extends SapphireTest {
7
8
	/**
9
	 *
10
	 * @var Config
11
	 */
12
	private $config = null;
13
14
	public function setUp() {
15
		parent::setUp();
16
		$this->config = clone(Config::inst());
17
	}
18
19
	public function tearDown() {
20
		parent::tearDown();
21
		Config::set_instance($this->config);
22
		PasswordEncryptor_Blowfish::set_cost(10);
23
	}
24
25
	public function testCreateForCode() {
26
		Config::inst()->update(
27
			'SilverStripe\\Security\\PasswordEncryptor',
28
			'encryptors',
29
			['test' => ['PasswordEncryptorTest_TestEncryptor' => null]]
30
		);
31
		$e = PasswordEncryptor::create_for_algorithm('test');
32
		$this->assertInstanceOf('PasswordEncryptorTest_TestEncryptor', $e );
33
	}
34
35
	/**
36
	 * @expectedException SilverStripe\Security\PasswordEncryptor_NotFoundException
37
	 */
38
	public function testCreateForCodeNotFound() {
39
		PasswordEncryptor::create_for_algorithm('unknown');
40
	}
41
42
	public function testRegister() {
43
		Config::inst()->update(
44
			'SilverStripe\\Security\\PasswordEncryptor',
45
			'encryptors',
46
			array('test' => array('PasswordEncryptorTest_TestEncryptor' => null))
47
		);
48
		$encryptors = PasswordEncryptor::get_encryptors();
49
		$this->assertContains('test', array_keys($encryptors));
50
		$encryptor = $encryptors['test'];
51
		$this->assertContains('PasswordEncryptorTest_TestEncryptor', key($encryptor));
52
	}
53
54
	public function testUnregister() {
55
		Config::inst()->update(
56
			'SilverStripe\\Security\\PasswordEncryptor',
57
			'encryptors',
58
			array('test' => array('PasswordEncryptorTest_TestEncryptor' => null))
59
		);
60
		Config::inst()->remove('SilverStripe\\Security\\PasswordEncryptor', 'encryptors', 'test');
61
		$this->assertNotContains('test', array_keys(PasswordEncryptor::get_encryptors()));
62
	}
63
64
	public function testEncryptorPHPHashWithArguments() {
65
		Config::inst()->update(
66
			'SilverStripe\\Security\\PasswordEncryptor',
67
			'encryptors',
68
			['test_md5' => ['SilverStripe\\Security\\PasswordEncryptor_PHPHash'=>'md5']]
69
		);
70
		$e = PasswordEncryptor::create_for_algorithm('test_md5');
71
		$this->assertEquals('md5', $e->getAlgorithm());
72
	}
73
74
	public function testEncryptorPHPHash() {
75
		Config::inst()->update(
76
			'SilverStripe\\Security\\PasswordEncryptor',
77
			'encryptors',
78
			['test_sha1' => ['SilverStripe\\Security\\PasswordEncryptor_PHPHash' => 'sha1']]
79
		);
80
		$e = PasswordEncryptor::create_for_algorithm('test_sha1');
81
		$password = 'mypassword';
82
		$salt = 'mysalt';
83
		$this->assertEquals(
84
			hash('sha1', $password . $salt),
85
			$e->encrypt($password, $salt)
86
		);
87
	}
88
89
	public function testEncryptorBlowfish() {
90
		Config::inst()->update(
91
			'SilverStripe\\Security\\PasswordEncryptor',
92
			'encryptors',
93
			['test_blowfish' => ['SilverStripe\\Security\\PasswordEncryptor_Blowfish' => '']]
94
		);
95
		$e = PasswordEncryptor::create_for_algorithm('test_blowfish');
96
97
		$password = 'mypassword';
98
99
		$salt = $e->salt($password);
100
		$modSalt = substr($salt, 0, 3) . str_shuffle(substr($salt, 3, strlen($salt)));
101
102
		$this->assertTrue($e->checkAEncryptionLevel() == 'y' || $e->checkAEncryptionLevel() == 'x'
0 ignored issues
show
Bug introduced by
The method checkAEncryptionLevel() does not exist on SilverStripe\Security\PasswordEncryptor. Did you maybe mean encrypt()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
103
			|| $e->checkAEncryptionLevel() == 'a');
0 ignored issues
show
Bug introduced by
The method checkAEncryptionLevel() does not exist on SilverStripe\Security\PasswordEncryptor. Did you maybe mean encrypt()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
104
		$this->assertTrue($e->check($e->encrypt($password, $salt), "mypassword", $salt));
105
		$this->assertFalse($e->check($e->encrypt($password, $salt), "anotherpw", $salt));
106
		$this->assertFalse($e->check($e->encrypt($password, $salt), "mypassword", $modSalt));
107
108
		PasswordEncryptor_Blowfish::set_cost(1);
109
		$salt = $e->salt($password);
110
		$modSalt = substr($salt, 0, 3) . str_shuffle(substr($salt, 3, strlen($salt)));
111
112
		$this->assertNotEquals(1, PasswordEncryptor_Blowfish::get_cost());
113
		$this->assertEquals(4, PasswordEncryptor_Blowfish::get_cost());
114
115
		$this->assertTrue($e->check($e->encrypt($password, $salt), "mypassword", $salt));
116
		$this->assertFalse($e->check($e->encrypt($password, $salt), "anotherpw", $salt));
117
		$this->assertFalse($e->check($e->encrypt($password, $salt), "mypassword", $modSalt));
118
119
		PasswordEncryptor_Blowfish::set_cost(11);
120
		$salt = $e->salt($password);
121
		$modSalt = substr($salt, 0, 3) . str_shuffle(substr($salt, 3, strlen($salt)));
122
123
		$this->assertEquals(11, PasswordEncryptor_Blowfish::get_cost());
124
125
		$this->assertTrue($e->check($e->encrypt($password, $salt), "mypassword", $salt));
126
		$this->assertFalse($e->check($e->encrypt($password, $salt), "anotherpw", $salt));
127
		$this->assertFalse($e->check($e->encrypt($password, $salt), "mypassword", $modSalt));
128
129
130
		PasswordEncryptor_Blowfish::set_cost(35);
131
132
		$this->assertNotEquals(35, PasswordEncryptor_Blowfish::get_cost());
133
		$this->assertEquals(31, PasswordEncryptor_Blowfish::get_cost());
134
135
		//Don't actually test this one. It takes too long. 31 takes too long to process
136
	}
137
138
	public function testEncryptorPHPHashCheck() {
139
		Config::inst()->update(
140
			'SilverStripe\\Security\\PasswordEncryptor',
141
			'encryptors',
142
			['test_sha1' => ['SilverStripe\\Security\\PasswordEncryptor_PHPHash' => 'sha1']]
143
		);
144
		$e = PasswordEncryptor::create_for_algorithm('test_sha1');
145
		$this->assertTrue($e->check(sha1('mypassword'), 'mypassword'));
146
		$this->assertFalse($e->check(sha1('mypassword'), 'mywrongpassword'));
147
	}
148
149
	/**
150
	 * See http://open.silverstripe.org/ticket/3004
151
	 *
152
	 * Handy command for reproducing via CLI on different architectures:
153
	 * 	php -r "echo(base_convert(sha1('mypassword'), 16, 36));"
154
	 */
155
	public function testEncryptorLegacyPHPHashCheck() {
156
		Config::inst()->update(
157
			'SilverStripe\\Security\\PasswordEncryptor',
158
			'encryptors',
159
			['test_sha1legacy' => ['SilverStripe\\Security\\PasswordEncryptor_LegacyPHPHash' => 'sha1']]
160
		);
161
		$e = PasswordEncryptor::create_for_algorithm('test_sha1legacy');
162
		// precomputed hashes for 'mypassword' from different architectures
163
		$amdHash = 'h1fj0a6m4o6k0sosks88oo08ko4gc4s';
164
		$intelHash = 'h1fj0a6m4o0g04ocg00o4kwoc4wowws';
165
		$wrongHash = 'h1fjxxxxxxxxxxxxxxxxxxxxxxxxxxx';
166
		$this->assertTrue($e->check($amdHash, "mypassword"));
167
		$this->assertTrue($e->check($intelHash, "mypassword"));
168
		$this->assertFalse($e->check($wrongHash, "mypassword"));
169
	}
170
}
171
172
class PasswordEncryptorTest_TestEncryptor extends PasswordEncryptor implements TestOnly {
173
	public function encrypt($password, $salt = null, $member = null) {
174
		return 'password';
175
	}
176
177
	public function salt($password, $member = null) {
178
		return 'salt';
179
	}
180
}
181