<?php

/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */

/**
 * Class to calculate RFC 2104 compliant hashes
 *
 *
 * PHP versions 4 and 5
 *
 * LICENSE: This source file is subject to version 3.0 of the PHP license
 * that is available through the world-wide-web at the following URI:
 * https://www.php.net/license/3_0.txt.  If you did not receive a copy of
 * the PHP License and are unable to obtain it through the web, please
 * send a note to license@php.net so we can mail you a copy immediately.
 *
 * @category   Encryption
 * @package    Crypt_HMAC
 * @author     Derick Rethans <derick@php.net>
 * @author     Matthew Fonda <mfonda@dotgeek.org>
 * @copyright  1997-2008 The PHP Group
 * @license    https://www.php.net/license/3_0.txt  PHP License 3.0
 * @version    CVS: $Id: HMAC.php,v 1.2 2008/10/13 15:18:58 devincen Exp $
 * @link       https://pear.php.net/package/Crypt_HMAC
 */

/**
 * Calculates RFC 2104 compliant HMACs
 *
 * @access     public
 * @category   Encryption
 * @package    Crypt_HMAC
 * @author     Derick Rethans <derick@php.net>
 * @author     Matthew Fonda <mfonda@dotgeek.org>
 * @copyright  1997-2008 The PHP Group
 * @license    https://www.php.net/license/3_0.txt  PHP License 3.0
 * @link       https://pear.php.net/package/Crypt_HMAC
 */
class Crypt_HMAC {

    /**
     * Hash function to use
     * @var string
     * @access private
     */
    var $_func;

    /**
     * Inner padded key
     * @var string
     * @access private
     */
    var $_ipad;

    /**
     * Outer padded key
     * @var string
     * @access private
     */
    var $_opad;

    /**
     * Pack format
     * @var string
     * @access private
     */
    var $_pack;

    /**
     * Constructor
     * Pass method as first parameter
     *
     * @param string $key  Key to use for hash
     * @param string $func  Hash function used for the calculation
     * @return void
     * @access public
     */
    function __construct($key, $func = 'md5') {
        $this->setFunction($func);
        $this->setKey($key);
    }

    /**
     * Sets hash function
     *
     * @param string $func  Hash function to use
     * @return void
     * @access public
     */
    function setFunction($func) {
        if (!$this->_pack = $this->_getPackFormat($func)) {
            die('Unsupported hash function');
        }
        $this->_func = $func;
    }

    /**
     * Sets key to use with hash
     *
     * @param string $key
     * @return void
     * @access public
     */
    function setKey($key) {
        /*
         * Pad the key as the RFC wishes
         */
        $func = $this->_func;

        if (strlen($key) > 64) {
            $key = pack($this->_pack, $func($key));
        }
        if (strlen($key) < 64) {
            $key = str_pad($key, 64, chr(0));
        }


        /* Calculate the padded keys and save them */
        $this->_ipad = (substr($key, 0, 64) ^ str_repeat(chr(0x36), 64));
        $this->_opad = (substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64));
    }

    /**
     * Gets pack formats for specifed hash function
     *
     * @param string $func
     * @return mixed  false if hash function doesnt exist, pack format on success
     * @access private
     */
    function _getPackFormat($func) {
        $packs = array('md5' => 'H32', 'sha1' => 'H40');
        return isset($packs[$func]) ? $packs[$func] : false;
    }

    /**
     * Hashing function
     *
     * @param  string $data  string that will encrypted
     * @return string
     * @access public
     */
    function hash($data) {
        $func = $this->_func;
        return $func($this->_opad . pack($this->_pack, $func($this->_ipad . $data)));
    }

}

?>