AbstractMcryptMixer.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. <?php
  2. /*
  3. * The RandomLib library for securely generating random numbers and strings in PHP
  4. *
  5. * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
  6. * @copyright 2011 The Authors
  7. * @license http://www.opensource.org/licenses/mit-license.html MIT License
  8. * @version Build @@version@@
  9. */
  10. /**
  11. * The Mcrypt abstract mixer class
  12. *
  13. * PHP version 5.3
  14. *
  15. * @category PHPCryptLib
  16. * @package Random
  17. * @subpackage Mixer
  18. *
  19. * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
  20. * @author Paragon Initiative Enterprises <security@paragonie.com>
  21. * @copyright 2013 The Authors
  22. * @license http://www.opensource.org/licenses/mit-license.html MIT License
  23. *
  24. * @version Build @@version@@
  25. */
  26. namespace RandomLib;
  27. /**
  28. * The mcrypt abstract mixer class
  29. *
  30. * @category PHPCryptLib
  31. * @package Random
  32. * @subpackage Mixer
  33. *
  34. * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
  35. * @author Chris Smith <chris@cs278.org>
  36. * @author Paragon Initiative Enterprises <security@paragonie.com>
  37. */
  38. abstract class AbstractMcryptMixer extends AbstractMixer
  39. {
  40. /**
  41. * mcrypt module resource
  42. *
  43. * @var resource
  44. */
  45. private $mcrypt;
  46. /**
  47. * Block size of cipher
  48. *
  49. * @var int
  50. */
  51. private $blockSize;
  52. /**
  53. * Cipher initialization vector
  54. *
  55. * @var string
  56. */
  57. private $initv;
  58. /**
  59. * {@inheritdoc}
  60. */
  61. public static function test()
  62. {
  63. return extension_loaded('mcrypt');
  64. }
  65. /**
  66. * @return bool
  67. */
  68. public static function advisable()
  69. {
  70. return static::test() && PHP_VERSION_ID < 70100;
  71. }
  72. /**
  73. * Construct mcrypt mixer
  74. * @psalm-suppress UndefinedConstant
  75. */
  76. public function __construct()
  77. {
  78. $this->mcrypt = mcrypt_module_open($this->getCipher(), '', MCRYPT_MODE_ECB, '');
  79. $this->blockSize = mcrypt_enc_get_block_size($this->mcrypt);
  80. $this->initv = str_repeat(chr(0), mcrypt_enc_get_iv_size($this->mcrypt));
  81. }
  82. /**
  83. * Performs cleanup
  84. */
  85. public function __destruct()
  86. {
  87. if ($this->mcrypt) {
  88. mcrypt_module_close($this->mcrypt);
  89. }
  90. }
  91. /**
  92. * Fetch the cipher for mcrypt.
  93. *
  94. * @return string
  95. */
  96. abstract protected function getCipher();
  97. /**
  98. * {@inheritdoc}
  99. */
  100. protected function getPartSize()
  101. {
  102. return $this->blockSize;
  103. }
  104. /**
  105. * {@inheritdoc}
  106. */
  107. protected function mixParts1($part1, $part2)
  108. {
  109. if (!\is_string($part1)) {
  110. throw new \InvalidArgumentException('Expected a string');
  111. }
  112. if (!\is_string($part2)) {
  113. throw new \InvalidArgumentException('Expected a string');
  114. }
  115. return $this->encryptBlock($part1, $part2);
  116. }
  117. /**
  118. * {@inheritdoc}
  119. */
  120. protected function mixParts2($part1, $part2)
  121. {
  122. if (!\is_string($part1)) {
  123. throw new \InvalidArgumentException('Expected a string');
  124. }
  125. if (!\is_string($part2)) {
  126. throw new \InvalidArgumentException('Expected a string');
  127. }
  128. return $this->decryptBlock($part2, $part1);
  129. }
  130. /**
  131. * Encrypts a block using the suppied key
  132. *
  133. * @param string $input Plaintext to encrypt
  134. * @param string $key Encryption key
  135. *
  136. * @return string Resulting ciphertext
  137. */
  138. private function encryptBlock($input, $key)
  139. {
  140. if (!$input && !$key) {
  141. return '';
  142. }
  143. $this->prepareCipher($key);
  144. $result = mcrypt_generic($this->mcrypt, $input);
  145. mcrypt_generic_deinit($this->mcrypt);
  146. return $result;
  147. }
  148. /**
  149. * Derypts a block using the suppied key
  150. *
  151. * @param string $input Ciphertext to decrypt
  152. * @param string $key Encryption key
  153. *
  154. * @return string Resulting plaintext
  155. */
  156. private function decryptBlock($input, $key)
  157. {
  158. if (!$input && !$key) {
  159. return '';
  160. }
  161. $this->prepareCipher($key);
  162. $result = mdecrypt_generic($this->mcrypt, $input);
  163. mcrypt_generic_deinit($this->mcrypt);
  164. return $result;
  165. }
  166. /**
  167. * Sets up the mcrypt module
  168. *
  169. * @param string $key
  170. *
  171. * @return void
  172. */
  173. private function prepareCipher($key)
  174. {
  175. if (0 !== mcrypt_generic_init($this->mcrypt, $key, $this->initv)) {
  176. throw new \RuntimeException('Failed to prepare mcrypt module');
  177. }
  178. }
  179. }