PageRenderTime 29ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/php/Security/PasswordEncryptorTest.php

http://github.com/silverstripe/sapphire
PHP | 168 lines | 131 code | 24 blank | 13 comment | 5 complexity | db1b5e1ab7e2fa86cf9fcf492e1f38e9 MD5 | raw file
Possible License(s): BSD-3-Clause, MIT, CC-BY-3.0, GPL-2.0, AGPL-1.0, LGPL-2.1
  1. <?php
  2. namespace SilverStripe\Security\Tests;
  3. use SilverStripe\Security\PasswordEncryptor_Blowfish;
  4. use SilverStripe\Security\PasswordEncryptor;
  5. use SilverStripe\Core\Config\Config;
  6. use SilverStripe\Dev\SapphireTest;
  7. use SilverStripe\Security\PasswordEncryptor_LegacyPHPHash;
  8. use SilverStripe\Security\PasswordEncryptor_PHPHash;
  9. use SilverStripe\Security\Tests\PasswordEncryptorTest\TestEncryptor;
  10. class PasswordEncryptorTest extends SapphireTest
  11. {
  12. protected function tearDown()
  13. {
  14. parent::tearDown();
  15. PasswordEncryptor_Blowfish::set_cost(10);
  16. }
  17. public function testCreateForCode()
  18. {
  19. Config::modify()->merge(
  20. PasswordEncryptor::class,
  21. 'encryptors',
  22. ['test' => [TestEncryptor::class => null]]
  23. );
  24. $e = PasswordEncryptor::create_for_algorithm('test');
  25. $this->assertInstanceOf(TestEncryptor::class, $e);
  26. }
  27. /**
  28. * @expectedException \SilverStripe\Security\PasswordEncryptor_NotFoundException
  29. */
  30. public function testCreateForCodeNotFound()
  31. {
  32. PasswordEncryptor::create_for_algorithm('unknown');
  33. }
  34. public function testRegister()
  35. {
  36. Config::modify()->merge(
  37. PasswordEncryptor::class,
  38. 'encryptors',
  39. ['test' => [TestEncryptor::class => null]]
  40. );
  41. $encryptors = PasswordEncryptor::get_encryptors();
  42. $this->assertContains('test', array_keys($encryptors));
  43. $encryptor = $encryptors['test'];
  44. $this->assertContains(TestEncryptor::class, key($encryptor));
  45. }
  46. public function testEncryptorPHPHashWithArguments()
  47. {
  48. Config::modify()->merge(
  49. PasswordEncryptor::class,
  50. 'encryptors',
  51. ['test_md5' => [PasswordEncryptor_PHPHash::class=>'md5']]
  52. );
  53. /** @var PasswordEncryptor_PHPHash $e */
  54. $e = PasswordEncryptor::create_for_algorithm('test_md5');
  55. $this->assertEquals('md5', $e->getAlgorithm());
  56. }
  57. public function testEncryptorPHPHash()
  58. {
  59. Config::modify()->merge(
  60. PasswordEncryptor::class,
  61. 'encryptors',
  62. ['test_sha1' => [PasswordEncryptor_PHPHash::class => 'sha1']]
  63. );
  64. $e = PasswordEncryptor::create_for_algorithm('test_sha1');
  65. $password = 'mypassword';
  66. $salt = 'mysalt';
  67. $this->assertEquals(
  68. hash('sha1', $password . $salt),
  69. $e->encrypt($password, $salt)
  70. );
  71. }
  72. public function testEncryptorBlowfish()
  73. {
  74. Config::modify()->merge(
  75. PasswordEncryptor::class,
  76. 'encryptors',
  77. ['test_blowfish' => [PasswordEncryptor_Blowfish::class => '']]
  78. );
  79. /** @var PasswordEncryptor_Blowfish $e */
  80. $e = PasswordEncryptor::create_for_algorithm('test_blowfish');
  81. $password = 'mypassword';
  82. $salt = $e->salt($password);
  83. $modSalt = substr($salt, 0, 3) . str_shuffle(substr($salt, 3, strlen($salt)));
  84. $this->assertTrue(
  85. $e->checkAEncryptionLevel() == 'y' || $e->checkAEncryptionLevel() == 'x'
  86. || $e->checkAEncryptionLevel() == 'a'
  87. );
  88. $this->assertTrue($e->check($e->encrypt($password, $salt), "mypassword", $salt));
  89. $this->assertFalse($e->check($e->encrypt($password, $salt), "anotherpw", $salt));
  90. $this->assertFalse($e->check($e->encrypt($password, $salt), "mypassword", $modSalt));
  91. PasswordEncryptor_Blowfish::set_cost(1);
  92. $salt = $e->salt($password);
  93. $modSalt = substr($salt, 0, 3) . str_shuffle(substr($salt, 3, strlen($salt)));
  94. $this->assertNotEquals(1, PasswordEncryptor_Blowfish::get_cost());
  95. $this->assertEquals(4, PasswordEncryptor_Blowfish::get_cost());
  96. $this->assertTrue($e->check($e->encrypt($password, $salt), "mypassword", $salt));
  97. $this->assertFalse($e->check($e->encrypt($password, $salt), "anotherpw", $salt));
  98. $this->assertFalse($e->check($e->encrypt($password, $salt), "mypassword", $modSalt));
  99. PasswordEncryptor_Blowfish::set_cost(11);
  100. $salt = $e->salt($password);
  101. $modSalt = substr($salt, 0, 3) . str_shuffle(substr($salt, 3, strlen($salt)));
  102. $this->assertEquals(11, PasswordEncryptor_Blowfish::get_cost());
  103. $this->assertTrue($e->check($e->encrypt($password, $salt), "mypassword", $salt));
  104. $this->assertFalse($e->check($e->encrypt($password, $salt), "anotherpw", $salt));
  105. $this->assertFalse($e->check($e->encrypt($password, $salt), "mypassword", $modSalt));
  106. PasswordEncryptor_Blowfish::set_cost(35);
  107. $this->assertNotEquals(35, PasswordEncryptor_Blowfish::get_cost());
  108. $this->assertEquals(31, PasswordEncryptor_Blowfish::get_cost());
  109. //Don't actually test this one. It takes too long. 31 takes too long to process
  110. }
  111. public function testEncryptorPHPHashCheck()
  112. {
  113. Config::modify()->merge(
  114. PasswordEncryptor::class,
  115. 'encryptors',
  116. ['test_sha1' => [PasswordEncryptor_PHPHash::class => 'sha1']]
  117. );
  118. $e = PasswordEncryptor::create_for_algorithm('test_sha1');
  119. $this->assertTrue($e->check(sha1('mypassword'), 'mypassword'));
  120. $this->assertFalse($e->check(sha1('mypassword'), 'mywrongpassword'));
  121. }
  122. /**
  123. * See http://open.silverstripe.org/ticket/3004
  124. *
  125. * Handy command for reproducing via CLI on different architectures:
  126. * php -r "echo(base_convert(sha1('mypassword'), 16, 36));"
  127. */
  128. public function testEncryptorLegacyPHPHashCheck()
  129. {
  130. Config::modify()->merge(
  131. PasswordEncryptor::class,
  132. 'encryptors',
  133. ['test_sha1legacy' => [PasswordEncryptor_LegacyPHPHash::class => 'sha1']]
  134. );
  135. $e = PasswordEncryptor::create_for_algorithm('test_sha1legacy');
  136. // precomputed hashes for 'mypassword' from different architectures
  137. $amdHash = 'h1fj0a6m4o6k0sosks88oo08ko4gc4s';
  138. $intelHash = 'h1fj0a6m4o0g04ocg00o4kwoc4wowws';
  139. $wrongHash = 'h1fjxxxxxxxxxxxxxxxxxxxxxxxxxxx';
  140. $this->assertTrue($e->check($amdHash, "mypassword"));
  141. $this->assertTrue($e->check($intelHash, "mypassword"));
  142. $this->assertFalse($e->check($wrongHash, "mypassword"));
  143. }
  144. }