File indexing completed on 2024-12-22 05:36:34

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_Crypt
0017  * @subpackage Hmac
0018  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0019  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0020  * @version    $Id$
0021  */
0022 
0023 /**
0024  * @see Zend_Crypt
0025  */
0026 // require_once 'Zend/Crypt.php';
0027 
0028 /**
0029  * PHP implementation of the RFC 2104 Hash based Message Authentication Code
0030  * algorithm.
0031  *
0032  * @todo  Patch for refactoring failed tests (key block sizes >80 using internal algo)
0033  * @todo       Check if mhash() is a required alternative (will be PECL-only soon)
0034  * @category   Zend
0035  * @package    Zend_Crypt
0036  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0037  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0038  */
0039 class Zend_Crypt_Hmac extends Zend_Crypt
0040 {
0041 
0042     /**
0043      * The key to use for the hash
0044      *
0045      * @var string
0046      */
0047     protected static $_key = null;
0048 
0049     /**
0050      * pack() format to be used for current hashing method
0051      *
0052      * @var string
0053      */
0054     protected static $_packFormat = null;
0055 
0056     /**
0057      * Hashing algorithm; can be the md5/sha1 functions or any algorithm name
0058      * listed in the output of PHP 5.1.2+ hash_algos().
0059      *
0060      * @var string
0061      */
0062     protected static $_hashAlgorithm = 'md5';
0063 
0064     /**
0065      * List of algorithms supported my mhash()
0066      *
0067      * @var array
0068      */
0069     protected static $_supportedMhashAlgorithms = array('adler32',' crc32', 'crc32b', 'gost',
0070             'haval128', 'haval160', 'haval192', 'haval256', 'md4', 'md5', 'ripemd160',
0071             'sha1', 'sha256', 'tiger', 'tiger128', 'tiger160');
0072 
0073     /**
0074      * Constants representing the output mode of the hash algorithm
0075      */
0076     const STRING = 'string';
0077     const BINARY = 'binary';
0078 
0079     /**
0080      * Performs a HMAC computation given relevant details such as Key, Hashing
0081      * algorithm, the data to compute MAC of, and an output format of String,
0082      * Binary notation or BTWOC.
0083      *
0084      * @param string $key
0085      * @param string $hash
0086      * @param string $data
0087      * @param string $output
0088      * @throws Zend_Crypt_Hmac_Exception
0089      * @return string
0090      */
0091     public static function compute($key, $hash, $data, $output = self::STRING)
0092     {
0093         // set the key
0094         if (!isset($key) || empty($key)) {
0095             // require_once 'Zend/Crypt/Hmac/Exception.php';
0096             throw new Zend_Crypt_Hmac_Exception('provided key is null or empty');
0097         }
0098         self::$_key = $key;
0099 
0100         // set the hash
0101         self::_setHashAlgorithm($hash);
0102 
0103         // perform hashing and return
0104         return self::_hash($data, $output);
0105     }
0106 
0107     /**
0108      * Setter for the hash method.
0109      *
0110      * @param string $hash
0111      * @throws Zend_Crypt_Hmac_Exception
0112      * @return Zend_Crypt_Hmac
0113      */
0114     protected static function _setHashAlgorithm($hash)
0115     {
0116         if (!isset($hash) || empty($hash)) {
0117             // require_once 'Zend/Crypt/Hmac/Exception.php';
0118             throw new Zend_Crypt_Hmac_Exception('provided hash string is null or empty');
0119         }
0120 
0121         $hash = strtolower($hash);
0122         $hashSupported = false;
0123 
0124         if (function_exists('hash_algos') && in_array($hash, hash_algos())) {
0125             $hashSupported = true;
0126         }
0127 
0128         if ($hashSupported === false && function_exists('mhash') && in_array($hash, self::$_supportedAlgosMhash)) {
0129             $hashSupported = true;
0130         }
0131 
0132         if ($hashSupported === false) {
0133             // require_once 'Zend/Crypt/Hmac/Exception.php';
0134             throw new Zend_Crypt_Hmac_Exception('hash algorithm provided is not supported on this PHP installation; please enable the hash or mhash extensions');
0135         }
0136         self::$_hashAlgorithm = $hash;
0137     }
0138 
0139     /**
0140      * Perform HMAC and return the keyed data
0141      *
0142      * @param string $data
0143      * @param string $output
0144      * @param bool $internal Option to not use hash() functions for testing
0145      * @return string
0146      */
0147     protected static function _hash($data, $output = self::STRING, $internal = false)
0148     {
0149         if (function_exists('hash_hmac')) {
0150             if ($output == self::BINARY) {
0151                 return hash_hmac(self::$_hashAlgorithm, $data, self::$_key, true);
0152             }
0153             return hash_hmac(self::$_hashAlgorithm, $data, self::$_key);
0154         }
0155 
0156         if (function_exists('mhash')) {
0157             if ($output == self::BINARY) {
0158                 return mhash(self::_getMhashDefinition(self::$_hashAlgorithm), $data, self::$_key);
0159             }
0160             $bin = mhash(self::_getMhashDefinition(self::$_hashAlgorithm), $data, self::$_key);
0161             return bin2hex($bin);
0162         }
0163     }
0164 
0165     /**
0166      * Since MHASH accepts an integer constant representing the hash algorithm
0167      * we need to make a small detour to get the correct integer matching our
0168      * algorithm's name.
0169      *
0170      * @param string $hashAlgorithm
0171      * @return integer
0172      */
0173     protected static function _getMhashDefinition($hashAlgorithm)
0174     {
0175         for ($i = 0; $i <= mhash_count(); $i++)
0176         {
0177             $types[mhash_get_hash_name($i)] = $i;
0178         }
0179         return $types[strtoupper($hashAlgorithm)];
0180     }
0181 
0182 }