PageRenderTime 156ms CodeModel.GetById 23ms RepoModel.GetById 2ms app.codeStats 0ms

/classes/crypt.php

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