統計
| ブランチ: | リビジョン:

pictcode / lib / Cake / Test / Case / Utility / SecurityTest.php @ 635eef61

履歴 | 表示 | アノテート | ダウンロード (11.621 KB)

1
<?php
2
/**
3
 * CakePHP(tm) Tests <http://book.cakephp.org/2.0/en/development/testing.html>
4
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
5
 *
6
 * Licensed under The MIT License
7
 * For full copyright and license information, please see the LICENSE.txt
8
 * Redistributions of files must retain the above copyright notice
9
 *
10
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
11
 * @link          http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
12
 * @since         CakePHP(tm) v 1.2.0.5432
13
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
14
 */
15

    
16
App::uses('Security', 'Utility');
17

    
18
/**
19
 * SecurityTest class
20
 *
21
 * @package       Cake.Test.Case.Utility
22
 */
23
class SecurityTest extends CakeTestCase {
24

    
25
/**
26
 * sut property
27
 *
28
 * @var mixed
29
 */
30
        public $sut = null;
31

    
32
/**
33
 * testInactiveMins method
34
 *
35
 * @return void
36
 */
37
        public function testInactiveMins() {
38
                Configure::write('Security.level', 'high');
39
                $this->assertEquals(10, Security::inactiveMins());
40

    
41
                Configure::write('Security.level', 'medium');
42
                $this->assertEquals(100, Security::inactiveMins());
43

    
44
                Configure::write('Security.level', 'low');
45
                $this->assertEquals(300, Security::inactiveMins());
46
        }
47

    
48
/**
49
 * testGenerateAuthkey method
50
 *
51
 * @return void
52
 */
53
        public function testGenerateAuthkey() {
54
                $this->assertEquals(strlen(Security::generateAuthKey()), 40);
55
        }
56

    
57
/**
58
 * testValidateAuthKey method
59
 *
60
 * @return void
61
 */
62
        public function testValidateAuthKey() {
63
                $authKey = Security::generateAuthKey();
64
                $this->assertTrue(Security::validateAuthKey($authKey));
65
        }
66

    
67
/**
68
 * testHashInvalidSalt method
69
 *
70
 * @expectedException PHPUnit_Framework_Error
71
 * @return void
72
 */
73
        public function testHashInvalidSalt() {
74
                Security::hash('someKey', 'blowfish', true);
75
        }
76

    
77
/**
78
 * testHashAnotherInvalidSalt
79
 *
80
 * @expectedException PHPUnit_Framework_Error
81
 * @return void
82
 */
83
        public function testHashAnotherInvalidSalt() {
84
                Security::hash('someKey', 'blowfish', '$1$lksdjoijfaoijs');
85
        }
86

    
87
/**
88
 * testHashYetAnotherInvalidSalt
89
 *
90
 * @expectedException PHPUnit_Framework_Error
91
 * @return void
92
 */
93
        public function testHashYetAnotherInvalidSalt() {
94
                Security::hash('someKey', 'blowfish', '$2a$10$123');
95
        }
96

    
97
/**
98
 * testHashInvalidCost method
99
 *
100
 * @expectedException PHPUnit_Framework_Error
101
 * @return void
102
 */
103
        public function testHashInvalidCost() {
104
                Security::setCost(1000);
105
        }
106
/**
107
 * testHash method
108
 *
109
 * @return void
110
 */
111
        public function testHash() {
112
                $_hashType = Security::$hashType;
113

    
114
                $key = 'someKey';
115
                $hash = 'someHash';
116

    
117
                $this->assertSame(40, strlen(Security::hash($key, null, false)));
118
                $this->assertSame(40, strlen(Security::hash($key, 'sha1', false)));
119
                $this->assertSame(40, strlen(Security::hash($key, null, true)));
120
                $this->assertSame(40, strlen(Security::hash($key, 'sha1', true)));
121

    
122
                $result = Security::hash($key, null, $hash);
123
                $this->assertSame($result, 'e38fcb877dccb6a94729a81523851c931a46efb1');
124

    
125
                $result = Security::hash($key, 'sha1', $hash);
126
                $this->assertSame($result, 'e38fcb877dccb6a94729a81523851c931a46efb1');
127

    
128
                $hashType = 'sha1';
129
                Security::setHash($hashType);
130
                $this->assertSame($hashType, Security::$hashType);
131
                $this->assertSame(40, strlen(Security::hash($key, null, true)));
132
                $this->assertSame(40, strlen(Security::hash($key, null, false)));
133

    
134
                $this->assertSame(32, strlen(Security::hash($key, 'md5', false)));
135
                $this->assertSame(32, strlen(Security::hash($key, 'md5', true)));
136

    
137
                $hashType = 'md5';
138
                Security::setHash($hashType);
139
                $this->assertSame($hashType, Security::$hashType);
140
                $this->assertSame(32, strlen(Security::hash($key, null, false)));
141
                $this->assertSame(32, strlen(Security::hash($key, null, true)));
142

    
143
                if (!function_exists('hash') && !function_exists('mhash')) {
144
                        $this->assertSame(32, strlen(Security::hash($key, 'sha256', false)));
145
                        $this->assertSame(32, strlen(Security::hash($key, 'sha256', true)));
146
                } else {
147
                        $this->assertSame(64, strlen(Security::hash($key, 'sha256', false)));
148
                        $this->assertSame(64, strlen(Security::hash($key, 'sha256', true)));
149
                }
150

    
151
                Security::setHash($_hashType);
152
        }
153

    
154
/**
155
 * Test that hash() works with blowfish.
156
 *
157
 * @return void
158
 */
159
        public function testHashBlowfish() {
160
                Security::setCost(10);
161
                $test = Security::hash('password', 'blowfish');
162
                $this->skipIf(strpos($test, '$2a$') === false, 'Blowfish hashes are incorrect.');
163

    
164
                $_hashType = Security::$hashType;
165

    
166
                $key = 'someKey';
167
                $hashType = 'blowfish';
168
                Security::setHash($hashType);
169

    
170
                $this->assertSame($hashType, Security::$hashType);
171
                $this->assertSame(60, strlen(Security::hash($key, null, false)));
172

    
173
                $password = $submittedPassword = $key;
174
                $storedPassword = Security::hash($password);
175

    
176
                $hashedPassword = Security::hash($submittedPassword, null, $storedPassword);
177
                $this->assertSame($storedPassword, $hashedPassword);
178

    
179
                $submittedPassword = 'someOtherKey';
180
                $hashedPassword = Security::hash($submittedPassword, null, $storedPassword);
181
                $this->assertNotSame($storedPassword, $hashedPassword);
182

    
183
                $expected = sha1('customsaltsomevalue');
184
                $result = Security::hash('somevalue', 'sha1', 'customsalt');
185
                $this->assertSame($expected, $result);
186

    
187
                $oldSalt = Configure::read('Security.salt');
188
                Configure::write('Security.salt', 'customsalt');
189

    
190
                $expected = sha1('customsaltsomevalue');
191
                $result = Security::hash('somevalue', 'sha1', true);
192
                $this->assertSame($expected, $result);
193

    
194
                Configure::write('Security.salt', $oldSalt);
195
                Security::setHash($_hashType);
196
        }
197

    
198
/**
199
 * testCipher method
200
 *
201
 * @return void
202
 */
203
        public function testCipher() {
204
                $length = 10;
205
                $txt = '';
206
                for ($i = 0; $i < $length; $i++) {
207
                        $txt .= mt_rand(0, 255);
208
                }
209
                $key = 'my_key';
210
                $result = Security::cipher($txt, $key);
211
                $this->assertEquals($txt, Security::cipher($result, $key));
212

    
213
                $txt = '';
214
                $key = 'my_key';
215
                $result = Security::cipher($txt, $key);
216
                $this->assertEquals($txt, Security::cipher($result, $key));
217

    
218
                $txt = 123456;
219
                $key = 'my_key';
220
                $result = Security::cipher($txt, $key);
221
                $this->assertEquals($txt, Security::cipher($result, $key));
222

    
223
                $txt = '123456';
224
                $key = 'my_key';
225
                $result = Security::cipher($txt, $key);
226
                $this->assertEquals($txt, Security::cipher($result, $key));
227
        }
228

    
229
/**
230
 * testCipherEmptyKey method
231
 *
232
 * @expectedException PHPUnit_Framework_Error
233
 * @return void
234
 */
235
        public function testCipherEmptyKey() {
236
                $txt = 'some_text';
237
                $key = '';
238
                Security::cipher($txt, $key);
239
        }
240

    
241
/**
242
 * testRijndael method
243
 *
244
 * @return void
245
 */
246
        public function testRijndael() {
247
                $this->skipIf(!function_exists('mcrypt_encrypt'));
248
                $txt = 'The quick brown fox jumped over the lazy dog.';
249
                $key = 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi';
250

    
251
                $result = Security::rijndael($txt, $key, 'encrypt');
252
                $this->assertEquals($txt, Security::rijndael($result, $key, 'decrypt'));
253

    
254
                $result = Security::rijndael($key, $txt, 'encrypt');
255
                $this->assertEquals($key, Security::rijndael($result, $txt, 'decrypt'));
256

    
257
                $result = Security::rijndael('', $key, 'encrypt');
258
                $this->assertEquals('', Security::rijndael($result, $key, 'decrypt'));
259

    
260
                $key = 'this is my key of over 32 chars, yes it is';
261
                $result = Security::rijndael($txt, $key, 'encrypt');
262
                $this->assertEquals($txt, Security::rijndael($result, $key, 'decrypt'));
263
        }
264

    
265
/**
266
 * Test that rijndael() can still decrypt values with a fixed iv.
267
 *
268
 * @return void
269
 */
270
        public function testRijndaelBackwardCompatibility() {
271
                $this->skipIf(!function_exists('mcrypt_encrypt'));
272

    
273
                $txt = 'The quick brown fox jumped over the lazy dog.';
274
                $key = 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi';
275

    
276
                // Encrypted before random iv
277
                $value = base64_decode('1WPjnq96LMzLGwNgmudHF+cAIqVUN5DaUZEpf5tm1EzSgt5iYY9o3d66iRI/fKJLTlTVGsa8HzW0jDNitmVXoQ==');
278
                $this->assertEquals($txt, Security::rijndael($value, $key, 'decrypt'));
279
        }
280

    
281
/**
282
 * testRijndaelInvalidOperation method
283
 *
284
 * @expectedException PHPUnit_Framework_Error
285
 * @return void
286
 */
287
        public function testRijndaelInvalidOperation() {
288
                $txt = 'The quick brown fox jumped over the lazy dog.';
289
                $key = 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi';
290
                Security::rijndael($txt, $key, 'foo');
291
        }
292

    
293
/**
294
 * testRijndaelInvalidKey method
295
 *
296
 * @expectedException PHPUnit_Framework_Error
297
 * @return void
298
 */
299
        public function testRijndaelInvalidKey() {
300
                $txt = 'The quick brown fox jumped over the lazy dog.';
301
                $key = 'too small';
302
                Security::rijndael($txt, $key, 'encrypt');
303
        }
304

    
305
/**
306
 * Test encrypt/decrypt.
307
 *
308
 * @return void
309
 */
310
        public function testEncryptDecrypt() {
311
                $txt = 'The quick brown fox';
312
                $key = 'This key is longer than 32 bytes long.';
313
                $result = Security::encrypt($txt, $key);
314
                $this->assertNotEquals($txt, $result, 'Should be encrypted.');
315
                $this->assertNotEquals($result, Security::encrypt($txt, $key), 'Each result is unique.');
316
                $this->assertEquals($txt, Security::decrypt($result, $key));
317
        }
318

    
319
/**
320
 * Test that changing the key causes decryption to fail.
321
 *
322
 * @return void
323
 */
324
        public function testDecryptKeyFailure() {
325
                $txt = 'The quick brown fox';
326
                $key = 'This key is longer than 32 bytes long.';
327
                Security::encrypt($txt, $key);
328

    
329
                $key = 'Not the same key. This one will fail';
330
                $this->assertFalse(Security::decrypt($txt, $key), 'Modified key will fail.');
331
        }
332

    
333
/**
334
 * Test that decrypt fails when there is an hmac error.
335
 *
336
 * @return void
337
 */
338
        public function testDecryptHmacFailure() {
339
                $txt = 'The quick brown fox';
340
                $key = 'This key is quite long and works well.';
341
                $salt = 'this is a delicious salt!';
342
                $result = Security::encrypt($txt, $key, $salt);
343

    
344
                // Change one of the bytes in the hmac.
345
                $result[10] = 'x';
346
                $this->assertFalse(Security::decrypt($result, $key, $salt), 'Modified hmac causes failure.');
347
        }
348

    
349
/**
350
 * Test that changing the hmac salt will cause failures.
351
 *
352
 * @return void
353
 */
354
        public function testDecryptHmacSaltFailure() {
355
                $txt = 'The quick brown fox';
356
                $key = 'This key is quite long and works well.';
357
                $salt = 'this is a delicious salt!';
358
                $result = Security::encrypt($txt, $key, $salt);
359

    
360
                $salt = 'humpty dumpty had a great fall.';
361
                $this->assertFalse(Security::decrypt($result, $key, $salt), 'Modified salt causes failure.');
362
        }
363

    
364
/**
365
 * Test that short keys cause errors
366
 *
367
 * @expectedException CakeException
368
 * @expectedExceptionMessage Invalid key for encrypt(), key must be at least 256 bits (32 bytes) long.
369
 * @return void
370
 */
371
        public function testEncryptInvalidKey() {
372
                $txt = 'The quick brown fox jumped over the lazy dog.';
373
                $key = 'this is too short';
374
                Security::encrypt($txt, $key);
375
        }
376

    
377
/**
378
 * Test encrypting falsey data
379
 *
380
 * @return void
381
 */
382
        public function testEncryptDecryptFalseyData() {
383
                $key = 'This is a key that is long enough to be ok.';
384

    
385
                $result = Security::encrypt('', $key);
386
                $this->assertSame('', Security::decrypt($result, $key));
387

    
388
                $result = Security::encrypt(false, $key);
389
                $this->assertSame('', Security::decrypt($result, $key));
390

    
391
                $result = Security::encrypt(null, $key);
392
                $this->assertSame('', Security::decrypt($result, $key));
393

    
394
                $result = Security::encrypt(0, $key);
395
                $this->assertSame('0', Security::decrypt($result, $key));
396

    
397
                $result = Security::encrypt('0', $key);
398
                $this->assertSame('0', Security::decrypt($result, $key));
399
        }
400

    
401
/**
402
 * Test that short keys cause errors
403
 *
404
 * @expectedException CakeException
405
 * @expectedExceptionMessage Invalid key for decrypt(), key must be at least 256 bits (32 bytes) long.
406
 * @return void
407
 */
408
        public function testDecryptInvalidKey() {
409
                $txt = 'The quick brown fox jumped over the lazy dog.';
410
                $key = 'this is too short';
411
                Security::decrypt($txt, $key);
412
        }
413

    
414
/**
415
 * Test that empty data cause errors
416
 *
417
 * @expectedException CakeException
418
 * @expectedExceptionMessage The data to decrypt cannot be empty.
419
 * @return void
420
 */
421
        public function testDecryptInvalidData() {
422
                $txt = '';
423
                $key = 'This is a key that is long enough to be ok.';
424
                Security::decrypt($txt, $key);
425
        }
426

    
427
}