Project

General

Profile

« Previous | Next » 

Revision 1506

Added by DarkViper almost 13 years ago

new class PasswordHash
new Password-/Hash-generator
(step to fix password-issues)

View differences:

branches/2.8.x/CHANGELOG
12 12

  
13 13
=============================== FEATURES FREEZE ================================
14 14
----------------------------------- Fixes 2.8.2 --------------------------------
15
26 Aug-2011 Build 1506 Werner v.d.Decken(DarkViper)
16
+ new class PasswordHash
17
+ new Password-/Hash-generator
15 18
19 Aug-2011 Build 1505 Dietmar Woellbrink (Luisehahne)
16 19
# syntaxfix order::clean()
17 20
19 Aug-2011 Build 1504 Werner v.d.Decken(DarkViper)
branches/2.8.x/wb/admin/interface/version.php
52 52

  
53 53
// check if defined to avoid errors during installation (redirect to admin panel fails if PHP error/warnings are enabled)
54 54
if(!defined('VERSION')) define('VERSION', '2.8.2');
55
if(!defined('REVISION')) define('REVISION', '1505');
55
if(!defined('REVISION')) define('REVISION', '1506');
branches/2.8.x/wb/framework/PasswordHash.php
1
<?php
2
/**
3
 * @category     Core
4
 * @package      Core_security
5
 * @author       Werner v.d.Decken
6
 * @copyright    ISTeasy-project(http://isteasy.de/)
7
 * @license      Creative Commons BY-SA 3.0 http://creativecommons.org/licenses/by-sa/3.0/
8
 * @version      $Id$
9
 * @filesource   $HeadURL:$
10
 * @since        Datei vorhanden seit Release 2.8.2
11
 * @lastmodified $Date:$
12
 *
13
 * this class works with salted md5-hashes with several rounds. 
14
 * For backward compatibility it can compare normal md5-hashes also.
15
 *
16
 * *****************************************************************************
17
 * This class is based on the Portable PHP password hashing framework.
18
 * Version 0.3 / genuine. Written by Solar Designer <solar at openwall.com>
19
 * in 2004-2006 and placed in the public domain. Revised in subsequent years,
20
 * still public domain. There's absolutely no warranty.
21
 * The homepage URL for this framework is: http://www.openwall.com/phpass/
22
 * *****************************************************************************
23
 */
24
class PasswordHash {
25

  
26

  
27
	private $_itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
28
	private $_iterationCountLog2 = 8;
29
	private $_portableHashes = true;
30
	private $_randomState = '';
31
	
32
	/**
33
	 * @param int $iterationCountLog2 number of iterations as exponent of 2
34
	 * @param bool $portableHashes TRUE = use MD5 only | FALSE = automatic
35
	 */
36
	public function __construct($iterationCountLog2, $portableHashes = true)
37
	{
38

  
39
		if ($iterationCountLog2 < 4 || $iterationCountLog2 > 31) {
40
			$iterationCountLog2 = 8;
41
		}
42
		$this->_iterationCountLog2 = $iterationCountLog2;
43
		$this->_portableHashes = $portableHashes;
44
		$this->_randomState = microtime();
45
		if (function_exists('getmypid')) {
46
			$this->_randomState .= getmypid();
47
		}
48
	}
49

  
50

  
51
	private function _getRandomBytes($count)
52
	{
53
		$output = '';
54
		if (is_readable('/dev/urandom') && ($fh = @fopen('/dev/urandom', 'rb'))) {
55
			$output = fread($fh, $count);
56
			fclose($fh);
57
		}
58
		if (strlen($output) < $count) {
59
			$output = '';
60
			for ($i = 0; $i < $count; $i += 16) {
61
				$this->_randomState = md5(microtime() . $this->_randomState);
62
				$output .= pack('H*', md5($this->_randomState));
63
			}
64
			$output = substr($output, 0, $count);
65
		}
66
		return $output;
67
	}
68

  
69
	private function _Encode64($input, $count)
70
	{
71
		$output = '';
72
		$i = 0;
73
		do {
74
			$value = ord($input[$i++]);
75
			$output .= $this->_itoa64[$value & 0x3f];
76
			if ($i < $count) {
77
				$value |= ord($input[$i]) << 8;
78
			}
79
			$output .= $this->_itoa64[($value >> 6) & 0x3f];
80
			if ($i++ >= $count) { break; }
81
			if ($i < $count) {
82
				$value |= ord($input[$i]) << 16;
83
			}
84
			$output .= $this->_itoa64[($value >> 12) & 0x3f];
85
			if ($i++ >= $count) { break; }
86
			$output .= $this->_itoa64[($value >> 18) & 0x3f];
87
		} while ($i < $count);
88
		return $output;
89
	}
90

  
91
	private function _GenSaltPrivate($input)
92
	{
93
		$output = '$P$';
94
		$output .= $this->_itoa64[min($this->_iterationCountLog2 +
95
		                          ((PHP_VERSION >= '5') ? 5 : 3), 30)];
96
		$output .= $this->_Encode64($input, 6);
97
		return $output;
98
	}
99

  
100
	private function _CryptPrivate($password, $setting)
101
	{
102
		$output = '*0';
103
		if (substr($setting, 0, 2) == $output) {
104
			$output = '*1';
105
		}
106
		$id = substr($setting, 0, 3);
107
		# We use "$P$", phpBB3 uses "$H$" for the same thing
108
		if ($id != '$P$' && $id != '$H$') {
109
			return $output;
110
		}
111
		$count_log2 = strpos($this->_itoa64, $setting[3]);
112
		if ($count_log2 < 7 || $count_log2 > 30) {
113
			return $output;
114
		}
115
		$count = 1 << $count_log2;
116
		$salt = substr($setting, 4, 8);
117
		if (strlen($salt) != 8) {
118
			return $output;
119
		}
120
		# We're kind of forced to use MD5 here since it's the only
121
		# cryptographic primitive available in all versions of PHP
122
		# currently in use.  To implement our own low-level crypto
123
		# in PHP would result in much worse performance and
124
		# consequently in lower iteration counts and hashes that are
125
		# quicker to crack (by non-PHP code).
126
		if (PHP_VERSION >= '5') {
127
			$hash = md5($salt . $password, TRUE);
128
			do {
129
				$hash = md5($hash . $password, TRUE);
130
			} while (--$count);
131
		} else {
132
			$hash = pack('H*', md5($salt . $password));
133
			do {
134
				$hash = pack('H*', md5($hash . $password));
135
			} while (--$count);
136
		}
137
		$output = substr($setting, 0, 12);
138
		$output .= $this->_Encode64($hash, 16);
139
		return $output;
140
	}
141

  
142
	/**
143
	 * calculate the hash from a given password
144
	 * @param string $password password as original string
145
	 * @return string generated hash | '*' on error
146
	 */
147
	public function HashPassword($password)
148
	{
149
		$random = '';
150
		if (strlen($random) < 6) {
151
			$random = $this->_getRandomBytes(6);
152
		}
153
		$hash = $this->_CryptPrivate($password, $this->_GenSaltPrivate($random));
154
		if (strlen($hash) == 34) {
155
			return $hash;
156
		}
157
		# Returning '*' on error is safe here, but would _not_ be safe
158
		# in a crypt(3)-like function used _both_ for generating new
159
		# hashes and for validating passwords against existing hashes.
160
		return '*';
161
	}
162

  
163
	/**
164
	 * encodes the password and compare it against the given hash
165
	 * @param string $password clear password
166
	 * @param string $stored_hash the hash to compare against
167
	 * @return bool
168
	 */
169
	public function CheckPassword($password, $stored_hash)
170
	{
171
	// compare against a normal, simple md5-hash
172
		if(preg_match('/^[0-9a-f]{32}$/i', $stored_hash)) {
173
			return md5($password) == $stored_hash;
174
		}
175
	// compare against a rounded, salted md5-hash
176
		$hash = $this->_CryptPrivate($password, $stored_hash);
177
		if ($hash[0] == '*') {
178
			$hash = crypt($password, $stored_hash);
179
		}
180
		return $hash == $stored_hash;
181
	}
182
	/**
183
	 * generate a case sensitive mnemonic password including numbers and special chars
184
	 * makes no use of lowercase 'l', uppercase 'I', 'O' or number '0'
185
	 * @param int $length length of the generated password. default = 8
186
	 * @return string
187
	 */
188
	public static function NewPassword($length = 8)
189
	{
190
		$chars = array(
191
			array('b','c','d','f','g','h','j','k','l','m','n','p','r','s','t','v','w','x','y','z'),
192
			array('a','e','i','o','u'),
193
			array('!','-','@','_',':','.','+','%','/','*')
194
		);
195
		$length = ceil($length / 2);
196
		$Password = array();
197
	// at first fill array alternating with vowels and consonants
198
		for($x = 0; $x < $length; $x++) {
199
			$char = $chars[0][rand(1000, 10000) % sizeof($chars[0])];
200
			$Password[] = $char == 'l' ? 'L' : $char;
201
			$Password[] = $chars[1][rand(1000, 10000) % sizeof($chars[1])];
202
		}
203
	// transform 2 random chars into uppercase
204
		for($x = 0; $x < 2; $x++) {
205
			$pos = rand(1000, 10000) % sizeof($Password);
206
			$Password[$pos] = ($Password[$pos] == 'i' || $Password[$pos] == 'o')
207
			                  ? $Password[$pos] : strtoupper($Password[$pos]);
208
		}
209
	// randomly insert one special char, but not at position 0 or as last char
210
		$pos = (rand(1000, 10000) % (sizeof($Password)-2))+1;
211
		$Password[$pos] = $chars[2][rand(1000, 10000) % sizeof($chars[2])];
212
	// randomly insert a numeric char, between 1 and 9
213
		$pos = rand(1000, 10000) % sizeof($Password);
214
		$Password[$pos] = (rand(1000, 10000) % 9) + 1;
215

  
216
		return implode($Password);
217
	}
218

  
219
} // end of class
branches/2.8.x/wb/pwgen.php
1
<?php
2
/**
3
 * @category     Core
4
 * @package      Core_security
5
 * @author       Werner v.d.Decken
6
 * @copyright    ISTeasy-project(http://isteasy.de/)
7
 * @license      Creative Commons BY-SA 3.0 http://creativecommons.org/licenses/by-sa/3.0/
8
 * @version      $Id$
9
 * @filesource   $HeadURL:$
10
 * @since        Datei vorhanden seit Release 2.8.2
11
 * @lastmodified $Date:$
12
 *
13
 * this class works with salted md5-hashes with several rounds. 
14
 * For backward compatibility it can compare normal md5-hashes also.
15
 *
16
 */
17
 $path2class = './framework/PasswordHash.php';
18
	$newpass = '';
19
	$pass    = '';
20
	$hash    = '';
21

  
22
	include $path2class;
23
	if(!isset($_POST['action']) ) { $_POST['action'] = 'pass'; }
24
	if($_POST['action'] == 'hash') {
25
		if(isset($_POST['pass']) && trim($_POST['pass']) != '') {
26
			$pass = trim($_POST['pass']);
27
			$newpass = $pass;
28
			$ph = new PasswordHash(12);
29
			$hash = $ph->HashPassword($pass);
30
		}
31
	}else {
32
		if(!isset($_POST['length']) ) { $_POST['length'] = 8; }
33
		$length = intval($_POST['length']);
34
		$newpass = PasswordHash::NewPassword($length);
35
		$pass = $newpass;
36
	}
37

  
38
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
39
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="de" lang="de">
40
	<head>
41
		<title>PWH-Generator v.0.1</title>
42
		<meta http-equiv="content-type" content="text/html; charset=utf-8" />
43
		<meta name="author" content="Werner von der Decken" />
44
		<meta name="copyright" content="ISTeasy, W.v.d.Decken" />
45
		<meta name="generator" content="ISTeasy - PWH-Generator v.0.1" />
46
		<style type="text/css">
47
			html { /* Schrifteinstellung für das ganze Dokument */
48
				font-family: "Trebuchet MS",Verdana, Arial, Helvetica, sans-serif;
49
				font-size: 78%;
50
				font-weight: normal;
51
				color: #303030;
52
				min-height: 100.2%;
53
			}
54
			body {
55
				text-align: center;
56
				padding-top: 4em;
57
			}
58
			.body {
59
				width: 40em;
60
				margin: auto;
61
			}
62
			fieldset {
63
				padding: 1em 0;
64
			}
65
			legend {
66
				font-size: 1.3em;
67
			}
68
			input {
69
				width: 90%;
70
				margin: 0.5em 0;
71
				padding: 3px;
72
				font-size: 1.2em;
73
			}
74
			#hash { font-size: 1em; }
75
		</style>
76
		<script type="text/javascript">
77
			function clearHash() {
78
				document.genhash.hash.value = "";
79
			}
80

  
81
		</script>
82
	</head>
83
	<body>
84
		<div class="body">
85
			<h1>PWH-Generator v.0.1</h1>
86
			<fieldset>
87
				<legend>&nbsp;Password-Generator&nbsp;</legend>
88
				<form  method="post" name="genpass" action="">
89
					<input type="hidden" name="action" value="pass" />
90
					<label for="length">length of password </label>&nbsp;&nbsp;
91
					<input type="radio" name="length" value="6">06</input>&nbsp;
92
					<input type="radio" name="length" value="8" checked="checked">08</input>&nbsp;
93
					<input type="radio" name="length" value="10">10</input>&nbsp;
94
					<input type="radio" name="length" value="12">12</input>&nbsp;
95
					<input type="radio" name="length" value="14">14</input>&nbsp;
96
					<input type="radio" name="length" value="16">16</input>&nbsp;
97
					<input type="radio" name="length" value="18">18</input>&nbsp;
98
					<input type="radio" name="length" value="20">20</input>&nbsp;<br /><br />
99
					<label for="pass">Our password suggestion</label><br />
100
					<input type="text" id="pass" name="pass" value="<?php echo $newpass; ?>" readonly="readonly" /><br /><br />
101
					<input name="submit" id="submit1" type="submit" value="suggest password" />
102
				</form>
103
			</fieldset><br /><br />
104
			<fieldset>
105
				<legend>&nbsp;Hash-Generator&nbsp;</legend>
106
				<form  method="post" name="genhash" action="">
107
					<input type="hidden" name="action" value="hash" />
108
					<label for="pass">Enter Text to hash</label><br />
109
					<input type="text" id="pass" name="pass" value="<?php echo $pass; ?>" onkeypress="clearHash();" /><br />
110
					<label for="hash">Hash to copy</label><br />
111
					<input type="text" id="hash" name="hash" value="<?php echo $hash; ?>" readonly="readonly" /><br /><br />
112
					<input name="submit" id="submit0" type="submit" value="calculate hash" />
113
				</form>
114
			</fieldset>
115
		</div>
116
	</body>
117
</html>
118

  

Also available in: Unified diff