crypter.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. <?php namespace Laravel; defined('DS') or die('No direct script access.');
  2. class Crypter {
  3. /**
  4. * The encryption cipher.
  5. *
  6. * @var string
  7. */
  8. public static $cipher = MCRYPT_RIJNDAEL_256;
  9. /**
  10. * The encryption mode.
  11. *
  12. * @var string
  13. */
  14. public static $mode = MCRYPT_MODE_CBC;
  15. /**
  16. * The block size of the cipher.
  17. *
  18. * @var int
  19. */
  20. public static $block = 32;
  21. /**
  22. * Encrypt a string using Mcrypt.
  23. *
  24. * The string will be encrypted using the AES-256 scheme and will be base64 encoded.
  25. *
  26. * @param string $value
  27. * @return string
  28. */
  29. public static function encrypt($value)
  30. {
  31. $iv = mcrypt_create_iv(static::iv_size(), static::randomizer());
  32. $value = static::pad($value);
  33. $value = mcrypt_encrypt(static::$cipher, static::key(), $value, static::$mode, $iv);
  34. return base64_encode($iv.$value);
  35. }
  36. /**
  37. * Decrypt a string using Mcrypt.
  38. *
  39. * @param string $value
  40. * @return string
  41. */
  42. public static function decrypt($value)
  43. {
  44. $value = base64_decode($value);
  45. // To decrypt the value, we first need to extract the input vector and
  46. // the encrypted value. The input vector size varies across different
  47. // encryption ciphers and modes, so we'll get the correct size.
  48. $iv = substr($value, 0, static::iv_size());
  49. $value = substr($value, static::iv_size());
  50. // Once we have the input vector and the value, we can give them both
  51. // to Mcrypt for decryption. The value is sometimes padded with \0,
  52. // so we will trim all of the padding characters.
  53. $key = static::key();
  54. $value = mcrypt_decrypt(static::$cipher, $key, $value, static::$mode, $iv);
  55. return static::unpad($value);
  56. }
  57. /**
  58. * Get the most secure random number generator for the system.
  59. *
  60. * @return int
  61. */
  62. protected static function randomizer()
  63. {
  64. // There are various sources from which we can get random numbers
  65. // but some are more random than others. We'll choose the most
  66. // random source we can for this server environment.
  67. if (defined('MCRYPT_DEV_URANDOM'))
  68. {
  69. return MCRYPT_DEV_URANDOM;
  70. }
  71. elseif (defined('MCRYPT_DEV_RANDOM'))
  72. {
  73. return MCRYPT_DEV_RANDOM;
  74. }
  75. // When using the default random number generator, we'll seed
  76. // the generator on each call to ensure the results are as
  77. // random as we can possibly get them.
  78. else
  79. {
  80. mt_srand();
  81. return MCRYPT_RAND;
  82. }
  83. }
  84. /**
  85. * Get the input vector size for the cipher and mode.
  86. *
  87. * @return int
  88. */
  89. protected static function iv_size()
  90. {
  91. return mcrypt_get_iv_size(static::$cipher, static::$mode);
  92. }
  93. /**
  94. * Add PKCS7 compatible padding on the given value.
  95. *
  96. * @param string $value
  97. * @return string
  98. */
  99. protected static function pad($value)
  100. {
  101. $pad = static::$block - (Str::length($value) % static::$block);
  102. return $value .= str_repeat(chr($pad), $pad);
  103. }
  104. /**
  105. * Remove the PKCS7 compatible padding from the given value.
  106. *
  107. * @param string $value
  108. * @return string
  109. */
  110. protected static function unpad($value)
  111. {
  112. $pad = ord($value[($length = Str::length($value)) - 1]);
  113. if ($pad and $pad < static::$block)
  114. {
  115. // If the correct padding is present on the string, we will remove
  116. // it and return the value. Otherwise, we'll throw an exception
  117. // as the padding appears to have been changed.
  118. if (preg_match('/'.chr($pad).'{'.$pad.'}$/', $value))
  119. {
  120. return substr($value, 0, $length - $pad);
  121. }
  122. // If the padding characters do not match the expected padding
  123. // for the value we'll bomb out with an exception since the
  124. // encrypted value seems to have been changed.
  125. else
  126. {
  127. throw new \Exception("Decryption error. Padding is invalid.");
  128. }
  129. }
  130. return $value;
  131. }
  132. /**
  133. * Get the encryption key from the application configuration.
  134. *
  135. * @return string
  136. */
  137. protected static function key()
  138. {
  139. return Config::get('application.key');
  140. }
  141. }