Hmac.php 5.5 KB

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