Hmac.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Crypt
  17. * @subpackage Hmac
  18. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id$
  21. */
  22. /**
  23. * @see Zend_Crypt
  24. */
  25. #require_once 'Zend/Crypt.php';
  26. /**
  27. * PHP implementation of the RFC 2104 Hash based Message Authentication Code
  28. * algorithm.
  29. *
  30. * @todo Patch for refactoring failed tests (key block sizes >80 using internal algo)
  31. * @todo Check if mhash() is a required alternative (will be PECL-only soon)
  32. * @category Zend
  33. * @package Zend_Crypt
  34. * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
  35. * @license http://framework.zend.com/license/new-bsd New BSD License
  36. */
  37. class Zend_Crypt_Hmac extends Zend_Crypt
  38. {
  39. /**
  40. * The key to use for the hash
  41. *
  42. * @var string
  43. */
  44. protected static $_key = null;
  45. /**
  46. * pack() format to be used for current hashing method
  47. *
  48. * @var string
  49. */
  50. protected static $_packFormat = null;
  51. /**
  52. * Hashing algorithm; can be the md5/sha1 functions or any algorithm name
  53. * listed in the output of PHP 5.1.2+ hash_algos().
  54. *
  55. * @var string
  56. */
  57. protected static $_hashAlgorithm = 'md5';
  58. /**
  59. * List of algorithms supported my mhash()
  60. *
  61. * @var array
  62. */
  63. protected static $_supportedMhashAlgorithms = array('adler32',' crc32', 'crc32b', 'gost',
  64. 'haval128', 'haval160', 'haval192', 'haval256', 'md4', 'md5', 'ripemd160',
  65. 'sha1', 'sha256', 'tiger', 'tiger128', 'tiger160');
  66. /**
  67. * Constants representing the output mode of the hash algorithm
  68. */
  69. const STRING = 'string';
  70. const BINARY = 'binary';
  71. /**
  72. * Performs a HMAC computation given relevant details such as Key, Hashing
  73. * algorithm, the data to compute MAC of, and an output format of String,
  74. * Binary notation or BTWOC.
  75. *
  76. * @param string $key
  77. * @param string $hash
  78. * @param string $data
  79. * @param string $output
  80. * @throws Zend_Crypt_Hmac_Exception
  81. * @return string
  82. */
  83. public static function compute($key, $hash, $data, $output = self::STRING)
  84. {
  85. // set the key
  86. if (!isset($key) || empty($key)) {
  87. #require_once 'Zend/Crypt/Hmac/Exception.php';
  88. throw new Zend_Crypt_Hmac_Exception('provided key is null or empty');
  89. }
  90. self::$_key = $key;
  91. // set the hash
  92. self::_setHashAlgorithm($hash);
  93. // perform hashing and return
  94. return self::_hash($data, $output);
  95. }
  96. /**
  97. * Setter for the hash method.
  98. *
  99. * @param string $hash
  100. * @throws Zend_Crypt_Hmac_Exception
  101. * @return Zend_Crypt_Hmac
  102. */
  103. protected static function _setHashAlgorithm($hash)
  104. {
  105. if (!isset($hash) || empty($hash)) {
  106. #require_once 'Zend/Crypt/Hmac/Exception.php';
  107. throw new Zend_Crypt_Hmac_Exception('provided hash string is null or empty');
  108. }
  109. $hash = strtolower($hash);
  110. $hashSupported = false;
  111. if (function_exists('hash_algos') && in_array($hash, hash_algos())) {
  112. $hashSupported = true;
  113. }
  114. if ($hashSupported === false && function_exists('mhash') && in_array($hash, self::$_supportedAlgosMhash)) {
  115. $hashSupported = true;
  116. }
  117. if ($hashSupported === false) {
  118. #require_once 'Zend/Crypt/Hmac/Exception.php';
  119. throw new Zend_Crypt_Hmac_Exception('hash algorithm provided is not supported on this PHP installation; please enable the hash or mhash extensions');
  120. }
  121. self::$_hashAlgorithm = $hash;
  122. }
  123. /**
  124. * Perform HMAC and return the keyed data
  125. *
  126. * @param string $data
  127. * @param string $output
  128. * @param bool $internal Option to not use hash() functions for testing
  129. * @return string
  130. */
  131. protected static function _hash($data, $output = self::STRING, $internal = false)
  132. {
  133. if (function_exists('hash_hmac')) {
  134. if ($output == self::BINARY) {
  135. return hash_hmac(self::$_hashAlgorithm, $data, self::$_key, true);
  136. }
  137. return hash_hmac(self::$_hashAlgorithm, $data, self::$_key);
  138. }
  139. if (function_exists('mhash')) {
  140. if ($output == self::BINARY) {
  141. return mhash(self::_getMhashDefinition(self::$_hashAlgorithm), $data, self::$_key);
  142. }
  143. $bin = mhash(self::_getMhashDefinition(self::$_hashAlgorithm), $data, self::$_key);
  144. return bin2hex($bin);
  145. }
  146. }
  147. /**
  148. * Since MHASH accepts an integer constant representing the hash algorithm
  149. * we need to make a small detour to get the correct integer matching our
  150. * algorithm's name.
  151. *
  152. * @param string $hashAlgorithm
  153. * @return integer
  154. */
  155. protected static function _getMhashDefinition($hashAlgorithm)
  156. {
  157. for ($i = 0; $i <= mhash_count(); $i++)
  158. {
  159. $types[mhash_get_hash_name($i)] = $i;
  160. }
  161. return $types[strtoupper($hashAlgorithm)];
  162. }
  163. }