-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpasshash.php
More file actions
144 lines (133 loc) · 4.21 KB
/
passhash.php
File metadata and controls
144 lines (133 loc) · 4.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
<?php
/**
* passhash.php
*
* A strong password hashing class for PHP
*
* Copyright (c) 2010-2012 Brad Proctor. (http://bradleyproctor.com)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @author Brad Proctor
* @copyright Copyright (c) 2010-2012 Brad Proctor
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @link http://bradleyproctor.com/
* @version 1.9.1
*/
/**
* The Password class works by generating a 104-character hash. The first 16 characters are a unique
* salt value that is generated for each password. The rest of the 88 characters is the hash generated
* by the whirlpool algorithm, which is much stronger than common md5 or sha1 methods. The hash value is
* also created using the HMAC method and a site wide key is used to further secure the hash. The site
* wide key can be any value, but a very strong 80-character unique value for 'authPepper' can be generated at
* http://bradleyproctor.com/tools/salt.php
*
* Usage:
* $hash = Passhash::hash('password'); // Store this value in your database
*
* if (Passhash::compare('password', $hash) === true) {
* // Password is correct
* } else {
* // Password was incorrect
* }
*/
abstract class Passhash
{
/**
* Number of characters in the salt value
*/
const saltLength = 16;
/**
* a unique site-wide value (pepper) to compliment the unique salts.
* Change this to a unique value.
*/
const authPepper = 'jS#W_;[;sjiNOUc9NG,S3T76NOTmK~%mu|#WI9-v.l^Bt]6H)1wz:kc=hPtS+JZv)haB!0dTo}klfWrr';
/**
* Used for key stretching. It is used to calculate the number of iterations to run the
* hashing algorithm. Raise this to increase security, lower this to make it run faster. Default value
* is 5.
*/
const authLevel = 5;
/*************************************************************************************/
/**
* Generate a password salt
*
* @param int $length
* The number of characters that the salt should be
*
* @return string
* Returns a salt that can be used to salt a password hash
*
* @access private
*/
final private static function salt()
{
$salt = '';
while (strlen($salt) < static::saltLength) {
$salt .= pack('C', dechex(mt_rand()));
}
return substr(base64_encode($salt), 0, static::saltLength);
}
/**
* PBKDF2 Implementation (described in RFC 2898)
* Password-Based Key Derivation Function
* (Simplified, since some variables are known)
*
* @param string $password
* The plain text password
*
* @param string $salt
* The salt used to generate the hash
*
* @return string
* Derived key
*
* @access private
*/
final private static function pbkdf2($password, $salt)
{
$ib = $b = hash_hmac('whirlpool', $salt . static::authPepper, $password, true);
for ($i = 1; $i < static::authLevel * 1000; $i++) {
$ib ^= ($b = hash_hmac('whirlpool', $b . static::authPepper, $password, true));
}
return base64_encode($ib);
}
/**
* Generate a 104 character password hash
*
* @param string $password
* The plain text password
*
* @param string $salt
* The salt to use to generate the password
*
* @return string
* Returns the 104-character hashed and salted password
*
* @access public
*/
final public static function hash($password, $salt = null)
{
$salt or $salt = static::salt();
return $salt . static::pbkdf2($password, $salt);
}
/**
* Compare a password with a hash
*
* @param string $password
* The plain text password to compare
*
* @param string $hash
* The 104 character password hash
*
* @return bool
* Returns TRUE if the password matches, FALSE if not
*
* @access public
*/
final public static function compare($password, $hash)
{
return 0 === strcmp($hash, static::hash($password, substr($hash, 0, static::saltLength), static::authLevel));
}
}