Encrypt.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php defined('SYSPATH') OR die('No direct script access.');
  2. /**
  3. * The Encrypt library provides two-way encryption of text and binary strings
  4. * using the [Mcrypt](http://php.net/mcrypt) extension, which consists of three
  5. * parts: the key, the cipher, and the mode.
  6. *
  7. * The Key
  8. * : A secret passphrase that is used for encoding and decoding
  9. *
  10. * The Cipher
  11. * : A [cipher](http://php.net/mcrypt.ciphers) determines how the encryption
  12. * is mathematically calculated. By default, the "rijndael-128" cipher
  13. * is used. This is commonly known as "AES-128" and is an industry standard.
  14. *
  15. * The Mode
  16. * : The [mode](http://php.net/mcrypt.constants) determines how the encrypted
  17. * data is written in binary form. By default, the "nofb" mode is used,
  18. * which produces short output with high entropy.
  19. *
  20. * @package Kohana
  21. * @category Security
  22. * @author Kohana Team
  23. * @copyright (c) 2007-2012 Kohana Team
  24. * @license http://kohanaframework.org/license
  25. */
  26. class Kohana_Encrypt {
  27. /**
  28. * @var string default instance name
  29. */
  30. public static $default = 'default';
  31. /**
  32. * @var array Encrypt class instances
  33. */
  34. public static $instances = array();
  35. /**
  36. * @var string OS-dependent RAND type to use
  37. */
  38. protected static $_rand;
  39. /**
  40. * Returns a singleton instance of Encrypt. An encryption key must be
  41. * provided in your "encrypt" configuration file.
  42. *
  43. * $encrypt = Encrypt::instance();
  44. *
  45. * @param string $name configuration group name
  46. * @return Encrypt
  47. */
  48. public static function instance($name = NULL)
  49. {
  50. if ($name === NULL)
  51. {
  52. // Use the default instance name
  53. $name = Encrypt::$default;
  54. }
  55. if ( ! isset(Encrypt::$instances[$name]))
  56. {
  57. // Load the configuration data
  58. $config = Kohana::$config->load('encrypt')->$name;
  59. if ( ! isset($config['key']))
  60. {
  61. // No default encryption key is provided!
  62. throw new Kohana_Exception('No encryption key is defined in the encryption configuration group: :group',
  63. array(':group' => $name));
  64. }
  65. if ( ! isset($config['mode']))
  66. {
  67. // Add the default mode
  68. $config['mode'] = MCRYPT_MODE_NOFB;
  69. }
  70. if ( ! isset($config['cipher']))
  71. {
  72. // Add the default cipher
  73. $config['cipher'] = MCRYPT_RIJNDAEL_128;
  74. }
  75. // Create a new instance
  76. Encrypt::$instances[$name] = new Encrypt($config['key'], $config['mode'], $config['cipher']);
  77. }
  78. return Encrypt::$instances[$name];
  79. }
  80. /**
  81. * Creates a new mcrypt wrapper.
  82. *
  83. * @param string $key encryption key
  84. * @param string $mode mcrypt mode
  85. * @param string $cipher mcrypt cipher
  86. */
  87. public function __construct($key, $mode, $cipher)
  88. {
  89. // Find the max length of the key, based on cipher and mode
  90. $size = mcrypt_get_key_size($cipher, $mode);
  91. if (isset($key[$size]))
  92. {
  93. // Shorten the key to the maximum size
  94. $key = substr($key, 0, $size);
  95. }
  96. // Store the key, mode, and cipher
  97. $this->_key = $key;
  98. $this->_mode = $mode;
  99. $this->_cipher = $cipher;
  100. // Store the IV size
  101. $this->_iv_size = mcrypt_get_iv_size($this->_cipher, $this->_mode);
  102. }
  103. /**
  104. * Encrypts a string and returns an encrypted string that can be decoded.
  105. *
  106. * $data = $encrypt->encode($data);
  107. *
  108. * The encrypted binary data is encoded using [base64](http://php.net/base64_encode)
  109. * to convert it to a string. This string can be stored in a database,
  110. * displayed, and passed using most other means without corruption.
  111. *
  112. * @param string $data data to be encrypted
  113. * @return string
  114. */
  115. public function encode($data)
  116. {
  117. // Set the rand type if it has not already been set
  118. if (Encrypt::$_rand === NULL)
  119. {
  120. if (Kohana::$is_windows)
  121. {
  122. // Windows only supports the system random number generator
  123. Encrypt::$_rand = MCRYPT_RAND;
  124. }
  125. else
  126. {
  127. if (defined('MCRYPT_DEV_URANDOM'))
  128. {
  129. // Use /dev/urandom
  130. Encrypt::$_rand = MCRYPT_DEV_URANDOM;
  131. }
  132. elseif (defined('MCRYPT_DEV_RANDOM'))
  133. {
  134. // Use /dev/random
  135. Encrypt::$_rand = MCRYPT_DEV_RANDOM;
  136. }
  137. else
  138. {
  139. // Use the system random number generator
  140. Encrypt::$_rand = MCRYPT_RAND;
  141. }
  142. }
  143. }
  144. if (Encrypt::$_rand === MCRYPT_RAND)
  145. {
  146. // The system random number generator must always be seeded each
  147. // time it is used, or it will not produce true random results
  148. mt_srand();
  149. }
  150. // Create a random initialization vector of the proper size for the current cipher
  151. $iv = mcrypt_create_iv($this->_iv_size, Encrypt::$_rand);
  152. // Encrypt the data using the configured options and generated iv
  153. $data = mcrypt_encrypt($this->_cipher, $this->_key, $data, $this->_mode, $iv);
  154. // Use base64 encoding to convert to a string
  155. return base64_encode($iv.$data);
  156. }
  157. /**
  158. * Decrypts an encoded string back to its original value.
  159. *
  160. * $data = $encrypt->decode($data);
  161. *
  162. * @param string $data encoded string to be decrypted
  163. * @return FALSE if decryption fails
  164. * @return string
  165. */
  166. public function decode($data)
  167. {
  168. // Convert the data back to binary
  169. $data = base64_decode($data, TRUE);
  170. if ( ! $data)
  171. {
  172. // Invalid base64 data
  173. return FALSE;
  174. }
  175. // Extract the initialization vector from the data
  176. $iv = substr($data, 0, $this->_iv_size);
  177. if ($this->_iv_size !== strlen($iv))
  178. {
  179. // The iv is not the expected size
  180. return FALSE;
  181. }
  182. // Remove the iv from the data
  183. $data = substr($data, $this->_iv_size);
  184. // Return the decrypted data, trimming the \0 padding bytes from the end of the data
  185. return rtrim(mcrypt_decrypt($this->_cipher, $this->_key, $data, $this->_mode, $iv), "\0");
  186. }
  187. } // End Encrypt