McryptTest.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. declare(strict_types=1);
  7. /**
  8. * Test case for \Magento\Framework\Encryption\Adapter\Mcrypt
  9. */
  10. namespace Magento\Framework\Encryption\Test\Unit\Adapter;
  11. class McryptTest extends \PHPUnit\Framework\TestCase
  12. {
  13. private $key;
  14. private static $cipherInfo;
  15. private const SUPPORTED_CIPHER_MODE_COMBINATIONS = [
  16. MCRYPT_BLOWFISH => [MCRYPT_MODE_ECB],
  17. MCRYPT_RIJNDAEL_128 => [MCRYPT_MODE_ECB],
  18. MCRYPT_RIJNDAEL_256 => [MCRYPT_MODE_CBC],
  19. ];
  20. protected function setUp()
  21. {
  22. $this->key = substr(__CLASS__, -32, 32);
  23. }
  24. protected function getRandomString(int $length): string
  25. {
  26. $result = '';
  27. do {
  28. $result .= sha1(microtime());
  29. } while (strlen($result) < $length);
  30. return substr($result, -$length);
  31. }
  32. private function requireCipherInfo()
  33. {
  34. $filename = __DIR__ . '/../Crypt/_files/_cipher_info.php';
  35. if (!self::$cipherInfo) {
  36. self::$cipherInfo = include $filename;
  37. }
  38. }
  39. private function getKeySize(string $cipherName, string $modeName): int
  40. {
  41. $this->requireCipherInfo();
  42. return self::$cipherInfo[$cipherName][$modeName]['key_size'];
  43. }
  44. private function getInitVectorSize(string $cipherName, string $modeName): int
  45. {
  46. $this->requireCipherInfo();
  47. return self::$cipherInfo[$cipherName][$modeName]['iv_size'];
  48. }
  49. public function getCipherModeCombinations(): array
  50. {
  51. $result = [];
  52. foreach (self::SUPPORTED_CIPHER_MODE_COMBINATIONS as $cipher => $modes) {
  53. /** @var array $modes */
  54. foreach ($modes as $mode) {
  55. $result[$cipher . '-' . $mode] = [$cipher, $mode];
  56. }
  57. }
  58. return $result;
  59. }
  60. /**
  61. * @dataProvider getCipherModeCombinations
  62. */
  63. public function testConstructor(string $cipher, string $mode)
  64. {
  65. /* Generate random init vector */
  66. $initVector = $this->getRandomString($this->getInitVectorSize($cipher, $mode));
  67. $crypt = new \Magento\Framework\Encryption\Adapter\Mcrypt($this->key, $cipher, $mode, $initVector);
  68. $this->assertEquals($cipher, $crypt->getCipher());
  69. $this->assertEquals($mode, $crypt->getMode());
  70. $this->assertEquals($initVector, $crypt->getInitVector());
  71. }
  72. public function getConstructorExceptionData(): array
  73. {
  74. $key = substr(__CLASS__, -32, 32);
  75. $result = [];
  76. foreach (self::SUPPORTED_CIPHER_MODE_COMBINATIONS as $cipher => $modes) {
  77. /** @var array $modes */
  78. foreach ($modes as $mode) {
  79. $tooLongKey = str_repeat('-', $this->getKeySize($cipher, $mode) + 1);
  80. $tooShortInitVector = str_repeat('-', $this->getInitVectorSize($cipher, $mode) - 1);
  81. $tooLongInitVector = str_repeat('-', $this->getInitVectorSize($cipher, $mode) + 1);
  82. $result['tooLongKey-' . $cipher . '-' . $mode . '-false'] = [$tooLongKey, $cipher, $mode, false];
  83. $keyPrefix = 'key-' . $cipher . '-' . $mode;
  84. $result[$keyPrefix . '-tooShortInitVector'] = [$key, $cipher, $mode, $tooShortInitVector];
  85. $result[$keyPrefix . '-tooLongInitVector'] = [$key, $cipher, $mode, $tooLongInitVector];
  86. }
  87. }
  88. return $result;
  89. }
  90. /**
  91. * @dataProvider getConstructorExceptionData
  92. * @expectedException \Magento\Framework\Exception\LocalizedException
  93. */
  94. public function testConstructorException(string $key, string $cipher, string $mode, ?string $initVector = null)
  95. {
  96. new \Magento\Framework\Encryption\Adapter\Mcrypt($key, $cipher, $mode, $initVector);
  97. }
  98. public function testConstructorDefaults()
  99. {
  100. $cryptExpected = new \Magento\Framework\Encryption\Adapter\Mcrypt(
  101. $this->key,
  102. MCRYPT_BLOWFISH,
  103. MCRYPT_MODE_ECB,
  104. null
  105. );
  106. $cryptActual = new \Magento\Framework\Encryption\Adapter\Mcrypt($this->key);
  107. $this->assertEquals($cryptExpected->getCipher(), $cryptActual->getCipher());
  108. $this->assertEquals($cryptExpected->getMode(), $cryptActual->getMode());
  109. $this->assertEquals($cryptExpected->getInitVector(), $cryptActual->getInitVector());
  110. }
  111. public function getCryptData(): array
  112. {
  113. $fixturesFilename = __DIR__ . '/../Crypt/_files/_crypt_fixtures.php';
  114. $result = include $fixturesFilename;
  115. /* Restore encoded string back to binary */
  116. foreach ($result as &$cryptParams) {
  117. $cryptParams[5] = base64_decode($cryptParams[5]);
  118. }
  119. unset($cryptParams);
  120. return $result;
  121. }
  122. /**
  123. * @dataProvider getCryptData
  124. */
  125. public function testDecrypt(
  126. string $key,
  127. string $cipher,
  128. string $mode,
  129. ?string $initVector,
  130. string $expectedData,
  131. string $inputData
  132. ) {
  133. $crypt = new \Magento\Framework\Encryption\Adapter\Mcrypt($key, $cipher, $mode, $initVector);
  134. $actualData = $crypt->decrypt($inputData);
  135. $this->assertEquals($expectedData, $actualData);
  136. }
  137. /**
  138. * @dataProvider getCipherModeCombinations
  139. */
  140. public function testInitVectorNone(string $cipher, string $mode)
  141. {
  142. $crypt = new \Magento\Framework\Encryption\Adapter\Mcrypt(
  143. $this->key,
  144. $cipher,
  145. $mode,
  146. null
  147. );
  148. $actualInitVector = $crypt->getInitVector();
  149. $expectedInitVector = str_repeat("\0", $this->getInitVectorSize($cipher, $mode));
  150. $this->assertEquals($expectedInitVector, $actualInitVector);
  151. }
  152. }