secure_hash
[ class tree: secure_hash ] [ index: secure_hash ] [ all elements ]

Source for file secure_hash.class.php

Documentation is available at secure_hash.class.php

  1. <?php
  2. /**
  3.  * Secure password hashing class
  4.  * @package secure_hash
  5.  * @author Julius Beckmann
  6.  * @link http://juliusbeckmann.de/classes/secure_hash/
  7.  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  8.  * @filesource
  9.  */
  10. /**
  11.  * Secure password hashing class. A simple and easy to use class for secure
  12.  * password hashing. It is using random Salts and multiple hashing with random
  13.  * iterations. The class can be easily extended with own hashing methods.
  14.  * @name Secure password hashing class
  15.  * @version v0.1_2009.09.18
  16.  * @access public
  17.  * @package secure_hash
  18.  *      
  19.  *       Copyright 2009 Julius Beckmann
  20.  *      
  21.  *       This program is free software; you can redistribute it and/or modify
  22.  *       it under the terms of the GNU General Public License as published by
  23.  *       the Free Software Foundation; either version 2 of the License, or
  24.  *       (at your option) any later version.
  25.  *      
  26.  *       This program is distributed in the hope that it will be useful,
  27.  *       but WITHOUT ANY WARRANTY; without even the implied warranty of
  28.  *       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  29.  *       GNU General Public License for more details.
  30.  *      
  31.  *       You should have received a copy of the GNU General Public License
  32.  *       along with this program; if not, write to the Free Software
  33.  *       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  34.  *       MA 02110-1301, USA.
  35.  */
  36. class secure_hash {
  37.     
  38.     /**
  39.      * Default hashing method
  40.      * Check available _hash_* methods
  41.      * @access public
  42.      * @var string 
  43.      */
  44.     var $hashing_method = 'sha1';
  45.  
  46.     /**
  47.      * Delimiter used in formated hash
  48.      * @access public
  49.      * @var string 
  50.      */
  51.     var $delimiter = '$';
  52.  
  53.     /**
  54.      * Length of salt
  55.      * @access public
  56.      * @var int 
  57.      */
  58.     var $salt_len = 4;
  59.     
  60.     /**
  61.      * Salt chars.
  62.      * Just using special latin chars here so we wont break charset and avoid
  63.      * creating not secure salts. NO " and ' to avoid breaking queries.
  64.      * @access public
  65.      * @var string 
  66.      */
  67.     var $salt_chars = '^!%&/()=?+~#,.-;:_|<>@$';
  68.     
  69.     /**
  70.      * Global salt which is NOT stored inside formated hash
  71.      * but needed to check integrity of hash.
  72.      * This is a further security method to avoid hashes being cracked.
  73.      * Idea is to save salt in database, as well as in a config file or just here.
  74.      * A attacker would need access to both to gain enough data to crack these
  75.      * hashes. Changing this value leads to incorrect hashes.
  76.      * Just define it once and keep it.
  77.      * @access public
  78.      * @var string 
  79.      */
  80.     var $salt_global = '';
  81.  
  82.     /**
  83.      * Min hashing iterations
  84.      * Keep this at least at 10 to keep hashlength static
  85.      * @access public
  86.      * @var int 
  87.      */
  88.     var $iter_min = 10;
  89.  
  90.     /**
  91.      * Max hashing iterations
  92.      * Keep this under 100 to keep hashlength static
  93.      * @access public
  94.      * @var int 
  95.      */
  96.     var $iter_max = 99;
  97.     
  98.     /**
  99.      * Flag if permutations should be used
  100.      * @access public
  101.      * @var bool 
  102.      */
  103.     var $permutate = true;
  104.     
  105.     /**
  106.      * Rules for permutation.
  107.      * Add more rules to make hashing even more complex.
  108.      * Every rule gets applied
  109.      * @access public
  110.      * @var array 
  111.      */
  112.     var $permutations = array('0123456789abcdef|e875d60c4a2f1b93',
  113.                                                         '0123456789abcdef|7d15b9f3e60a82c4',
  114.                                                         '0123456789abcdef|b294cd1e6a038f57');
  115.                                                         
  116.     
  117.     // --- PUBLIC Functions ---    
  118.     
  119.     /**
  120.      * Hashes a string and returns the formated hash.
  121.      * @access public
  122.      * @param string $pass string to hash
  123.      * @param string $salt salt to use, default false
  124.      * @param integer $iter iterations to do, default false
  125.      * @return string hashed string
  126.      */
  127.     function hash($pass$salt=false$iter=false{
  128.         
  129.         // Generate salt if unspecified
  130.         if($salt === false)
  131.             $salt $this->_salt();
  132.             
  133.         // Random iterations if unspecified
  134.         if($iter === false)
  135.             $iter rand($this->iter_min$this->iter_max);
  136.         
  137.         // Check hashing function
  138.         $method '_hash_'.$this->hashing_method;
  139.         if(!method_exists($this$method))
  140.             die('ERROR: The hashing-method "'.$method.'" is NOT callable!');
  141.         
  142.         // Generate hash
  143.         $hash $this->$method($pass$salt.$this->salt_global$iter);
  144.         
  145.         // Return formated hash
  146.         $d $this->delimiter;
  147.         return $d.$this->hashing_method.$d.$salt.$d.$iter.$d.$hash.$d;
  148.     }
  149.  
  150.     /**
  151.      * Checks if a formated hash is equal to a password
  152.      * @access public
  153.      * @param string $hash_formated hash to use
  154.      * @param string $pass password to check
  155.      * @return boolean true is hash == pass
  156.      */
  157.     function check($hash_formated$pass{
  158.         $ret false;
  159.         // Check if first and last char of formated string are our delimiter
  160.         $len strlen($hash_formated);
  161.         if($len && $hash_formated[0== $this->delimiter 
  162.                 && $hash_formated[$len-1== $this->delimiter{
  163.                     
  164.             // Parse formated hash
  165.             list(,$hashmethod$salt$iter$hash
  166.                 = explode($this->delimiter$hash_formated);
  167.             
  168.             // Check hashing function
  169.             $method '_hash_'.$hashmethod;
  170.             if(!method_exists($this$method))
  171.                 die('ERROR: The hashing-method "'.$method.'" is NOT callable!');
  172.                 
  173.             // Check hash
  174.             $ret ($hash == $this->$method($pass$salt.$this->salt_global$iter));
  175.         }
  176.         return $ret;
  177.     }
  178.  
  179.     /**
  180.      * Returns a new permutaion which can be used in this class
  181.      * Permutation format is abc|cab - a->c && b->a && c->b
  182.      * Default base is 0..f     *
  183.      * @access public
  184.      * @param $b string base for permutation
  185.      * @return string permutation for this class
  186.      */
  187.     function _new_permutation($b=false{
  188.         if($b===false)
  189.             $b implode(''range(0,9)).implode(''range('a','f'));
  190.         return $b.'|'.str_shuffle($b);    
  191.     }
  192.  
  193.     // --- PRIVATE Functions ---
  194.     
  195.     /**
  196.      * Generate a random salt
  197.      * @access private
  198.      * @return string 
  199.      */
  200.     function _salt({
  201.         // Remove delimiter from salt chars
  202.         $chars str_ireplace($this->delimiter,''$this->salt_chars);
  203.         $char_count strlen($chars)-1;
  204.  
  205.         // Generate salt
  206.         $i 0;
  207.         $salt '';
  208.         while($i++ < $this->salt_len)
  209.             $salt .= $chars[rand(0$char_count)];
  210.         
  211.         return $salt;
  212.     }
  213.     
  214.     /**
  215.      * Plugin sha1 hashing method
  216.      * @access private
  217.      * @param string $str string to hash
  218.      * @param string $salt salt to use
  219.      * @param int $iter iterations to do
  220.      * @return string 
  221.      */
  222.     function _hash_sha1($str$salt$iter{
  223.         $hash $this->_p(sha1(sha1($str).sha1($salt)));
  224.         for($i=0$i<$iter++$i)
  225.             $hash $this->_p(sha1(sha1($str.$hash).sha1($hash).sha1($salt.$hash)));
  226.         return $hash;
  227.     }
  228.     
  229.     /**
  230.      * Plugin md5 hashing method
  231.      * @access private
  232.      * @param string $str string to hash
  233.      * @param string $salt salt to use
  234.      * @param int $iter iterations to do
  235.      * @return string 
  236.      */
  237.     function _hash_md5($str$salt$iter{
  238.         $hash $this->_p(md5(md5($str).md5($salt)));
  239.         for($i=0$i<$iter++$i)
  240.             $hash $this->_p(md5(md5($str.$hash).md5($hash).md5($salt.$hash)));
  241.         return $hash;
  242.     }
  243.  
  244.  
  245.     /**
  246.      * Permutation string with global rules
  247.      * @access private
  248.      * @param string string to permutate
  249.      * @return string permutated string
  250.      */
  251.     function _p($str{
  252.         if($this->permutate)
  253.             // Apply each permutation
  254.             foreach($this->permutations as $perm
  255.                 $this->_permutate($str$perm);
  256.         return $str;
  257.     }
  258.  
  259.     /**
  260.      * Permutate a string with given rule
  261.      * @access private
  262.      * @param string $str referece (faster) for the string to permutate
  263.      * @param string $perm rule in form of 123|312
  264.      * @param bool $dir direction to permutate. Default: true = forward
  265.      * @param integer $iter number of iterations to do. Default: depends on
  266.      *                                                                                      last char and length of $perm.
  267.      * @return bool always true.
  268.      *  */
  269.     function _permutate(&$str&$perm$dir=true$iter=false{
  270.         // Load permutation rule
  271.         if($dir
  272.             list($from$toexplode('|',$perm2);
  273.         else
  274.             list($to$fromexplode('|',$perm2);
  275.         
  276.         // Verify rule length
  277.         $len_base strlen($from);
  278.         if($len_base !== strlen($to))
  279.             return false// Rule is incorrect - stop here.
  280.             
  281.         // Get a new iterationcount depending on last rule char
  282.         if($iter === false)
  283.             $iter (ord($perm[strlen($perm)-1]($len_base/2));
  284.     
  285.         // Create permutation array
  286.         $p array();
  287.         for($i=0$i<$len_base++$i
  288.             $p[$from[$i]] $to[$i];
  289.             
  290.         // Apply permutation
  291.         $len strlen($str);
  292.         if($len >= 0)
  293.             for($i=0$i<$len++$i)
  294.                 if(isset($p[$str[$i]])) //This will keep chars that are not in our rule.
  295.                     $str[$i$p[$str[$i]];
  296.         if($iter 0)
  297.             $this->_permutate($str$perm$dir$iter-1);
  298.         return true;
  299.     }
  300.         
  301. }
  302.  
  303.  
  304. /**
  305.  * Example code how secure_hash can be easily extended for own hashing methods.
  306.  * @package secure_hash
  307.  */
  308. class secure_hash_example extends secure_hash {
  309.     
  310.     /**
  311.      * New default hashing function
  312.      */
  313.     var $hashing_method = 'own';
  314.     
  315.     /**
  316.      * Plugin own hashing method
  317.      * @param string $str string to hash
  318.      * @param string $salt salt to use
  319.      * @param int $iter iterations to do
  320.      * @return string 
  321.      */
  322.     function _hash_own($str$salt$iter{
  323.         // Some badass code :D
  324.         $hash $this->_p(sha1(md5($str.$salt).md5($str).md5($salt).md5($salt.$str)));
  325.         for($i=0$i<$iter++$i)
  326.             $hash $this->_p(sha1(md5($str.$hash).md5($hash).md5($salt.$hash)));
  327.         return $hash;
  328.     }
  329.     
  330. }
  331.  
  332. ?>

Documentation generated on Fri, 29 Jan 2010 08:49:11 +0100 by phpDocumentor 1.4.3