PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/fuel/core/classes/crypt.php

https://github.com/tilur/taranoelle
PHP | 195 lines | 104 code | 33 blank | 58 comment | 10 complexity | b40fcbf5aa23b0a91382fecbe3756359 MD5 | raw file
Possible License(s): MIT
  1. <?php
  2. /**
  3. * Fuel is a fast, lightweight, community driven PHP5 framework.
  4. *
  5. * @package Fuel
  6. * @version 1.0
  7. * @author Fuel Development Team
  8. * @license MIT License
  9. * @copyright 2010 - 2011 Fuel Development Team
  10. * @link http://fuelphp.com
  11. */
  12. namespace Fuel\Core;
  13. import('phpseclib/Crypt/AES', 'vendor');
  14. import('phpseclib/Crypt/Hash', 'vendor');
  15. use \PHPSecLib\Crypt_AES;
  16. use \PHPSecLib\Crypt_Hash;
  17. class Crypt {
  18. /*
  19. * Crypto object used to encrypt/decrypt
  20. *
  21. * @var object
  22. */
  23. private static $crypter = null;
  24. /*
  25. * Hash object used to generate hashes
  26. *
  27. * @var object
  28. */
  29. private static $hasher = null;
  30. /*
  31. * Crypto configuration
  32. *
  33. * @var array
  34. */
  35. private static $config = array();
  36. /*
  37. * initialisation and auto configuration
  38. */
  39. public static function _init()
  40. {
  41. static::$crypter = new Crypt_AES();
  42. static::$hasher = new Crypt_Hash('sha256');
  43. // load the config
  44. \Config::load('crypt', true);
  45. static::$config = \Config::get('crypt', array ());
  46. // generate random crypto keys if we don't have them or they are incorrect length
  47. $update = false;
  48. foreach(array('crypto_key', 'crypto_iv', 'crypto_hmac') as $key)
  49. {
  50. if ( empty(static::$config[$key]) || (strlen(static::$config[$key]) % 4) != 0)
  51. {
  52. $crypto = '';
  53. for ($i = 0; $i < 8; $i++) {
  54. $crypto .= static::safe_b64encode(pack('n', mt_rand(0, 0xFFFF)));
  55. }
  56. static::$config[$key] = $crypto;
  57. $update = true;
  58. }
  59. }
  60. // update the config if needed
  61. if ($update === true)
  62. {
  63. try
  64. {
  65. \Config::save('crypt', static::$config);
  66. }
  67. catch (\FileAccessException $e)
  68. {
  69. // failed to write the config file, inform the user
  70. echo \View::factory('errors/crypt_keys', array(
  71. 'keys' => static::$config
  72. ));
  73. die();
  74. }
  75. }
  76. static::$crypter->enableContinuousBuffer();
  77. static::$hasher->setKey(static::safe_b64decode(static::$config['crypto_hmac']));
  78. }
  79. // --------------------------------------------------------------------
  80. /*
  81. * encrypt a string value, optionally with a custom key
  82. *
  83. * @param string value to encrypt
  84. * @param string optional custom key to be used for this encryption
  85. * @access public
  86. * @return string encrypted value
  87. */
  88. public static function encode($value, $key = false)
  89. {
  90. $key ? static::$crypter->setKey($key) : static::$crypter->setKey(static::safe_b64decode(static::$config['crypto_key']));
  91. static::$crypter->setIV(static::safe_b64decode(static::$config['crypto_iv']));
  92. $value = static::$crypter->encrypt($value);
  93. return static::safe_b64encode(static::add_hmac($value));
  94. }
  95. // --------------------------------------------------------------------
  96. /*
  97. * decrypt a string value, optionally with a custom key
  98. *
  99. * @param string value to decrypt
  100. * @param string optional custom key to be used for this encryption
  101. * @access public
  102. * @return string encrypted value
  103. */
  104. public static function decode($value, $key = false)
  105. {
  106. $key ? static::$crypter->setKey($key) : static::$crypter->setKey(static::safe_b64decode(static::$config['crypto_key']));
  107. static::$crypter->setIV(static::safe_b64decode(static::$config['crypto_iv']));
  108. $value = static::safe_b64decode($value);
  109. if ($value = static::validate_hmac($value))
  110. {
  111. return static::$crypter->decrypt($value);
  112. }
  113. else
  114. {
  115. return false;
  116. }
  117. }
  118. // --------------------------------------------------------------------
  119. private static function safe_b64encode($value)
  120. {
  121. $data = base64_encode($value);
  122. $data = str_replace(array('+','/','='),array('-','_',''),$data);
  123. return $data;
  124. }
  125. private static function safe_b64decode($value)
  126. {
  127. $data = str_replace(array('-','_'),array('+','/'),$value);
  128. $mod4 = strlen($data) % 4;
  129. if ($mod4) {
  130. $data .= substr('====', $mod4);
  131. }
  132. return base64_decode($data);
  133. }
  134. private static function add_hmac($value)
  135. {
  136. // calculate the hmac-sha256 hash of this value
  137. $hmac = static::safe_b64encode(static::$hasher->hash($value));
  138. // append it and return the hmac protected string
  139. return $value.$hmac;
  140. }
  141. private static function validate_hmac($value)
  142. {
  143. // strip the hmac-sha256 hash from the value
  144. $hmac = substr($value, strlen($value)-43);
  145. // and remove it from the value
  146. $value = substr($value, 0, strlen($value)-43);
  147. // only return the value if it wasn't tampered with
  148. return (static::secure_compare(static::safe_b64encode(static::$hasher->hash($value)), $hmac)) ? $value : false;
  149. }
  150. private static function secure_compare($a, $b) {
  151. // make sure we're only comparing equal length strings
  152. if (strlen($a) !== strlen($b)) {
  153. return false;
  154. }
  155. // and that all comparisons take equal time
  156. $result = 0;
  157. for ($i = 0; $i < strlen($a); $i++) {
  158. $result |= ord($a[$i]) ^ ord($b[$i]);
  159. }
  160. return $result == 0;
  161. }
  162. }