Index: branches/2.8.x/CHANGELOG
===================================================================
--- branches/2.8.x/CHANGELOG	(revision 1899)
+++ branches/2.8.x/CHANGELOG	(revision 1900)
@@ -12,7 +12,8 @@
 ===============================================================================
 
 
-
+18 Apr-2013 Build 1900 Werner v.d.Decken(DarkViper)
++ Classes Password / PasswordHash Added for an essential strengthening of the password security
 04 Apr-2013 Build 1899 Dietmar Woellbrink (Luisehahne)
 # bugfix missing td in form layout
 03 Apr-2013 Build 1898 Dietmar Woellbrink (Luisehahne)
Index: branches/2.8.x/wb/include/phpass/PasswordHash.php
===================================================================
--- branches/2.8.x/wb/include/phpass/PasswordHash.php	(nonexistent)
+++ branches/2.8.x/wb/include/phpass/PasswordHash.php	(revision 1900)
@@ -0,0 +1,255 @@
+<?php
+/**
+ * Portable PHP password hashing framework.
+ *
+ * Version 0.4 / WebsiteBaker Rev. 0.1
+ * WB changes: added SHA-256, SHA-512 (2012/10/27 DarkViper)
+ *
+ * Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in
+ * the public domain.  Revised in subsequent years, still public domain.
+ *
+ * There's absolutely no warranty.
+ *
+ * The homepage URL for this framework is:
+ *
+ *	http://www.openwall.com/phpass/
+ *
+ * Please be sure to update the Version line if you edit this file in any way.
+ * It is suggested that you leave the main version number intact, but indicate
+ * your project name (after the slash) and add your own revision information.
+ *
+ * Please do not change the "private" password hashing method implemented in
+ * here, thereby making your hashes incompatible.  However, if you must, please
+ * change the hash type identifier (the "$P$") to something different.
+ *
+ * Obviously, since this code is in the public domain, the above are not
+ * requirements (there can be none), but merely suggestions.
+ */
+
+class PasswordHash {
+	private $itoa64;
+	private $itoa64BlowFish;
+	private $iteration_count_log2;
+	private $portable_hashes;
+	private $random_state;
+
+	public function __construct($iteration_count_log2, $portable_hashes)
+	{
+		$this->itoa64         = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
+		$this->itoa64BlowFish = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+
+		if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) {
+			$iteration_count_log2 = 8;
+		}
+		$this->iteration_count_log2 = $iteration_count_log2;
+		$this->portable_hashes = $portable_hashes;
+		$this->random_state = microtime();
+		if (function_exists('getmypid')) {
+			$this->random_state .= getmypid();
+		}
+	}
+
+	private function get_random_bytes($count)
+	{
+		$output = '';
+		if (@is_readable('/dev/urandom') &&
+		    ($fh = @fopen('/dev/urandom', 'rb'))) {
+			$output = fread($fh, $count);
+			fclose($fh);
+		}
+		if (strlen($output) < $count) {
+			$output = '';
+			for ($i = 0; $i < $count; $i += 16) {
+				$this->random_state = md5(microtime() . $this->random_state);
+				$output .= pack('H*', md5($this->random_state));
+			}
+			$output = substr($output, 0, $count);
+		}
+		return $output;
+	}
+
+	private function encode64($input, $count)
+	{
+		$output = '';
+		$i = 0;
+		do {
+			$value = ord($input[$i++]);
+			$output .= $this->itoa64[$value & 0x3f];
+			if ($i < $count) { $value |= ord($input[$i]) << 8; }
+			$output .= $this->itoa64[($value >> 6) & 0x3f];
+			if ($i++ >= $count) { break; }
+			if ($i < $count) { $value |= ord($input[$i]) << 16; }
+			$output .= $this->itoa64[($value >> 12) & 0x3f];
+			if ($i++ >= $count) { break; }
+			$output .= $this->itoa64[($value >> 18) & 0x3f];
+		} while ($i < $count);
+
+		return $output;
+	}
+
+	private function gensalt_private($input)
+	{
+		$output = '$P$';
+		$output .= $this->itoa64[min($this->iteration_count_log2 +
+			((PHP_VERSION >= '5') ? 5 : 3), 30)];
+		$output .= $this->encode64($input, 6);
+		return $output;
+	}
+
+	private function crypt_private($password, $setting)
+	{
+		$output = '*0';
+		if (substr($setting, 0, 2) == $output) { $output = '*1'; }
+		$id = substr($setting, 0, 3);
+		# We use "$P$", phpBB3 uses "$H$" for the same thing
+		if ($id != '$P$' && $id != '$H$') { return $output; }
+		$count_log2 = strpos($this->itoa64, $setting[3]);
+		if ($count_log2 < 7 || $count_log2 > 30) { return $output; }
+		$count = 1 << $count_log2;
+		$salt = substr($setting, 4, 8);
+		if (strlen($salt) != 8) { return $output; }
+
+		# We're kind of forced to use MD5 here since it's the only
+		# cryptographic primitive available in all versions of PHP
+		# currently in use.  To implement our own low-level crypto
+		# in PHP would result in much worse performance and
+		# consequently in lower iteration counts and hashes that are
+		# quicker to crack (by non-PHP code).
+		if (PHP_VERSION >= '5') {
+			$hash = md5($salt . $password, TRUE);
+			do {
+				$hash = md5($hash . $password, TRUE);
+			} while (--$count);
+		} else {
+			$hash = pack('H*', md5($salt . $password));
+			do {
+				$hash = pack('H*', md5($hash . $password));
+			} while (--$count);
+		}
+		$output = substr($setting, 0, 12);
+		$output .= $this->encode64($hash, 16);
+		return $output;
+	}
+
+	private function gensalt_extended($input)
+	{
+		$count_log2 = min($this->iteration_count_log2 + 8, 24);
+		# This should be odd to not reveal weak DES keys, and the
+		# maximum valid value is (2**24 - 1) which is odd anyway.
+		$count = (1 << $count_log2) - 1;
+		$output = '_';
+		$output .= $this->itoa64[$count & 0x3f];
+		$output .= $this->itoa64[($count >> 6) & 0x3f];
+		$output .= $this->itoa64[($count >> 12) & 0x3f];
+		$output .= $this->itoa64[($count >> 18) & 0x3f];
+		$output .= $this->encode64($input, 3);
+		return $output;
+	}
+/** Begin inserted function for WebsiteBaker by W.v.d.Decken **/	
+/**
+ * 
+ * @param type $input
+ * @param type $sType
+ * @return type
+ */
+	private function gensalt_sha($input, $sType = 'SHA512')
+	{
+		$iType = ($sType === 'SHA512') ? 6 : (($sType === 'SHA256') ? 5 : 6);
+		$iIterations = pow(2, $this->iteration_count_log2);
+		$iIterations = min(max($iIterations, 10000), 999999999);
+		$output = '$'.(string)$iType.'$rounds='.(string)$iIterations.'$';
+		$output .= $this->encode64($input, 16);
+		return $output;
+	}
+/** End inserted function for WebsiteBaker by W.v.d.Decken **/	
+
+	private function gensalt_blowfish($input)
+	{
+		# This one needs to use a different order of characters and a
+		# different encoding scheme from the one in encode64() above.
+		# We care because the last character in our encoded string will
+		# only represent 2 bits.  While two known implementations of
+		# bcrypt will happily accept and correct a salt string which
+		# has the 4 unused bits set to non-zero, we do not want to take
+		# chances and we also do not want to waste an additional byte
+		# of entropy.
+
+		$output = '$2a$';
+		$output .= chr(ord('0') + $this->iteration_count_log2 / 10);
+		$output .= chr(ord('0') + $this->iteration_count_log2 % 10);
+		$output .= '$';
+		$i = 0;
+		do {
+			$c1 = ord($input[$i++]);
+			$output .= $this->itoa64BlowFish[$c1 >> 2];
+			$c1 = ($c1 & 0x03) << 4;
+			if ($i >= 16) {
+				$output .= $this->itoa64BlowFish[$c1];
+				break;
+			}
+			$c2 = ord($input[$i++]);
+			$c1 |= $c2 >> 4;
+			$output .= $this->itoa64BlowFish[$c1];
+			$c1 = ($c2 & 0x0f) << 2;
+			$c2 = ord($input[$i++]);
+			$c1 |= $c2 >> 6;
+			$output .= $this->itoa64BlowFish[$c1];
+			$output .= $this->itoa64BlowFish[$c2 & 0x3f];
+		} while (1);
+		return $output;
+	}
+
+	public function HashPassword($password)
+	{
+		$random = '';
+
+/** Begin inserted function for WebsiteBaker by W.v.d.Decken **/	
+		if (CRYPT_SHA512 == 1 && !$this->portable_hashes) {
+			$random = $this->get_random_bytes(16);
+			$hash = crypt($password, $this->gensalt_sha($random, 'SHA512'));
+			if (strlen(substr(strrchr($hash, 36), 1)) == 86) { return $hash; }
+		}
+
+		if (CRYPT_SHA256 == 1 && !$this->portable_hashes) {
+			$random = $this->get_random_bytes(16);
+			$hash = crypt($password, $this->gensalt_sha($random, 'SHA256'));
+			if (strlen(substr(strrchr($hash, 36), 1)) == 43) { return $hash; }
+		}
+/** End inserted function for WebsiteBaker by W.v.d.Decken **/	
+
+		if (CRYPT_BLOWFISH == 1 && !$this->portable_hashes) {
+			$random = $this->get_random_bytes(16);
+			$hash = crypt($password, $this->gensalt_blowfish($random));
+			if (strlen($hash) == 60) { return $hash; }
+		}
+
+		if (CRYPT_EXT_DES == 1 && !$this->portable_hashes) {
+			if (strlen($random) < 3) {
+				$random = $this->get_random_bytes(3);
+			}
+			$hash = crypt($password, $this->gensalt_extended($random));
+			if (strlen($hash) == 20) { return $hash; }
+		}
+
+		if (strlen($random) < 6) {
+			$random = $this->get_random_bytes(6);
+		}
+		$hash = $this->crypt_private($password, $this->gensalt_private($random));
+		if (strlen($hash) == 34) { return $hash; }
+
+		# Returning '*' on error is safe here, but would _not_ be safe
+		# in a crypt(3)-like function used _both_ for generating new
+		# hashes and for validating passwords against existing hashes.
+		return '*';
+	}
+
+	public function CheckPassword($password, $stored_hash)
+	{
+		$hash = $this->crypt_private($password, $stored_hash);
+		if ($hash[0] == '*') {
+			$hash = crypt($password, $stored_hash);
+		}
+		return $hash == $stored_hash;
+	}
+}
+

Property changes on: branches/2.8.x/wb/include/phpass/PasswordHash.php
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Date Author Id Revision HeadURL
\ No newline at end of property
Index: branches/2.8.x/wb/admin/interface/version.php
===================================================================
--- branches/2.8.x/wb/admin/interface/version.php	(revision 1899)
+++ branches/2.8.x/wb/admin/interface/version.php	(revision 1900)
@@ -51,5 +51,5 @@
 
 // check if defined to avoid errors during installation (redirect to admin panel fails if PHP error/warnings are enabled)
 if(!defined('VERSION')) define('VERSION', '2.8.3');
-if(!defined('REVISION')) define('REVISION', '1899');
+if(!defined('REVISION')) define('REVISION', '1900');
 if(!defined('SP')) define('SP', '');
Index: branches/2.8.x/wb/framework/initialize.php
===================================================================
--- branches/2.8.x/wb/framework/initialize.php	(revision 1899)
+++ branches/2.8.x/wb/framework/initialize.php	(revision 1900)
@@ -208,6 +208,10 @@
 	if(!function_exists('globalExceptionHandler')) {
 		include(dirname(__FILE__).'/globalExceptionHandler.php');
 	}
+// activate secure PasswordHashes
+	if(!class_exists('PasswordHash')) {
+		include(dirname(dirname(__FILE__)).'/include/phpass/PasswordHash.php'); 
+	}
 // ---------------------------
 // Create global database instance ---
 	$database = WbDatabase::getInstance();
Index: branches/2.8.x/wb/framework/Password.php
===================================================================
--- branches/2.8.x/wb/framework/Password.php	(nonexistent)
+++ branches/2.8.x/wb/framework/Password.php	(revision 1900)
@@ -0,0 +1,193 @@
+<?php
+/**
+ *  Copyright (C) 2012 Werner v.d. Decken <wkl@isteam.de>
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+/**
+ * Description of Password
+ * *****************************************************************************
+ * This class is interfacing the Portable PHP password hashing framework.
+ * Version 0.4 / ISTeam Rev. 0.1
+ * ISTeam changes: added SHA-256, SHA-512 (2012/10/27 Werner v.d. Decken)
+ * *****************************************************************************
+ *
+ * @category     WBCore
+ * @package      WBCore_Security
+ * @author       Werner v.d. Decken <wkl@isteam.de>
+ * @copyright    Werner v.d. Decken <wkl@isteam.de>
+ * @license      http://www.gnu.org/licenses/gpl.html   GPL License
+ * @version      1.0.3
+ * @revision     $Revision$
+ * @link         $HeadURL$
+ * @lastmodified $Date$
+ * @since        Datei vorhanden seit Release 1.2.0
+ */
+
+// use \vendors\phpass\PasswordHash;
+
+class Password extends PasswordHash
+//class Password extends v_phpass_PasswordHash
+{
+
+	const MIN_CRYPT_LOOPS     =  6;  // minimum numbers of loops is 2^6 (64) very, very quick
+	const MAX_CRYPT_LOOPS     = 32;  // maximum numbers of loops is 2^32 (4,294,967,296) extremely slow
+	const DEFAULT_CRYPT_LOOPS = 12;  // default numbers of loopf is 2^12 (4096) a good average
+
+	const HASH_TYPE_PORTABLE  = true;  // use MD5 only
+	const HASH_TYPE_AUTO      = false; // select highest available crypting methode
+
+	const MIN_PW_LENGTH       =   6;
+	const MAX_PW_LENGTH       = 100;
+	const DEFAULT_PW_LENGTH   =  10;
+
+	const PW_USE_LOWERCHAR    = 0x0001; // use lower chars
+	const PW_USE_UPPERCHAR    = 0x0002; // use upper chars
+	const PW_USE_DIGITS       = 0x0004; // use numeric digits
+	const PW_USE_SPECIAL      = 0x0008; // use special chars
+	const PW_USE_ALL          = 0xFFFF; // use all possibilities
+
+/**
+ * @param int number of iterations as exponent of 2 (must be between 4 and 31)
+ * @param bool TRUE = use MD5 only | FALSE = automatic
+ */
+	public function __construct($iIterationCountLog2 = self::DEFAULT_CRYPT_LOOPS, $bPortableHashes = self::HASH_TYPE_AUTO)
+	{
+		parent::__construct($iIterationCountLog2, $bPortableHashes);
+	}
+/**
+ * @param string password to hash
+ * @return string generated hash. Null if failed.
+ */
+	public function HashPassword($sPassword)
+	{
+		$sNewHash = parent::HashPassword($sPassword);
+		return ($sNewHash == '*') ? null : $sNewHash;
+	}
+/**
+ * @param string Password to test against given Hash
+ * @param string existing stored hash
+ * @return bool true if PW matches the stored hash
+ */
+	public function CheckPassword($sPassword, $sStoredHash)
+	{
+		// compatibility layer for deprecated, simple and old MD5 hashes
+		if(preg_match('/^[0-9a-f]{32}$/si', $sStoredHash)) {
+			return (md5($sPassword) === $sStoredHash);
+		}
+		return parent::CheckPassword($sPassword, $sStoredHash);
+	}
+/**
+ * generate a case sensitive mnemonic password including numbers and special chars
+ * makes no use of confusing characters like 'O' and '0' and so on.
+ * @param int length of the generated password. default = DEFAULT_PW_LENGTH
+ * @param int defines which elemets are used to generate a password. Default = PW_USE_ALL
+ * @return string
+ */
+	public static function createNew($iLength = self::DEFAULT_PW_LENGTH, $iElements = self::PW_USE_ALL)
+	{
+		$aChars = array(
+			array('b','c','d','f','g','h','j','k','m','n','p','q','r','s','t','v','w','x','y','z'),
+			array('B','C','D','F','G','H','J','K','M','N','P','Q','R','S','T','V','W','X','Y','Z'),
+			array('a','e','i','o','u'),
+			array('A','E','U'),
+			array('!','-','@','_',':','.','+','%','/','*')
+		);
+		$iElements = ($iElements & self::PW_USE_ALL) == 0 ? self::PW_USE_ALL : $iElements;
+		if(($iLength < self::MIN_PW_LENGTH) || ($iLength > self::MAX_PW_LENGTH)) {
+			$iLength = self::DEFAULT_PW_LENGTH;
+		}
+	// at first create random arrays of lowerchars and uperchars
+	// alternating between vowels and consonants
+		$aUpperCase = array();
+		$aLowerCase = array();
+		for($x = 0; $x < ceil($iLength / 2); $x++) {
+			// consonants
+			$y = rand(1000, 10000) % sizeof($aChars[0]);
+			$aLowerCase[] = $aChars[0][$y];
+			$y = rand(1000, 10000) % sizeof($aChars[1]);
+			$aUpperCase[] = $aChars[1][$y];
+			// vowels
+			$y = rand(1000, 10000) % sizeof($aChars[2]);
+			$aLowerCase[] = $aChars[2][$y];
+			$y = rand(1000, 10000) % sizeof($aChars[3]);
+			$aUpperCase[] = $aChars[3][$y];
+		}
+	// create random arrays of numeric digits 2-9 and  special chars
+		$aDigits       = array();
+		$aSpecialChars = array();
+		for($x = 0; $x < $iLength; $x++) {
+			$aDigits[] = (rand(1000, 10000) % 8) + 2;
+			$aSpecialChars[] = $aChars[4][rand(1000, 10000) % sizeof($aChars[4])];
+		}
+		// take string or merge chars depending from $iElements
+		$aPassword = array();
+		$bMerge = false;
+		if($iElements & self::PW_USE_LOWERCHAR) {
+			$aPassword = $aLowerCase;
+			$bMerge = true;
+		}
+		if($iElements & self::PW_USE_UPPERCHAR) {
+			if($bMerge) {
+				$iNumberOfUpperChars = rand(1000, 10000) % ($iLength);
+				$aPassword = self::_mergeIntoPassword($aPassword, $aUpperCase, $iNumberOfUpperChars);
+			}else {
+				$aPassword = $aUpperCase;
+				$bMerge = true;
+			}
+		}
+		if($iElements & self::PW_USE_DIGITS) {
+			if($bMerge) {
+				$iNumberOfDigits = (rand(1000, 10000) % ceil($iLength / 2.5));
+				$iNumberOfDigits = $iNumberOfDigits ? $iNumberOfDigits : 1;
+				$aPassword = self::_mergeIntoPassword($aPassword, $aDigits, $iNumberOfDigits);
+			}else {
+				$aPassword = $aDigits;
+				$bMerge = true;
+			}
+		}
+		if($iElements & self::PW_USE_SPECIAL) {
+			if($bMerge) {
+				$iNumberOfSpecialChars = rand(1000, 10000) % ceil($iLength / 5);
+				$iNumberOfSpecialChars = $iNumberOfSpecialChars ? $iNumberOfSpecialChars : 1;
+				$aPassword = self::_mergeIntoPassword($aPassword, $aSpecialChars, $iNumberOfSpecialChars);
+			}else {
+				$aPassword = $aSpecialChars;
+				$bMerge = true;
+			}
+		}
+		$sPassword = implode('', array_slice($aPassword, 0, $iLength));
+		return $sPassword;
+	}
+/**
+ * merges $iCount chars from $aInsert randomly into $aPassword
+ * @param array $aPassword
+ * @param array $aInsert
+ * @param integer $iCount
+ * @return array
+ */
+	private static function _mergeIntoPassword($aPassword, $aInsert, $iCount)
+	{
+		$aListOfIndexes = array();
+		while(sizeof($aListOfIndexes) < $iCount) {
+			$x = rand(1000, 10000) % sizeof($aInsert);
+			$aListOfIndexes[$x] = $x;
+		}
+		foreach($aListOfIndexes as $x) {
+			$aPassword[$x] = $aInsert[$x];
+		}
+		return $aPassword;
+	}
+
+} // end of class PasswordHash

Property changes on: branches/2.8.x/wb/framework/Password.php
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Date Author Id Revision HeadURL
\ No newline at end of property
