Skip to content

Commit 11c3629

Browse files
committed
[phpsec#41] Moved password hashing methods to phpsecPw class.
1 parent e7e93aa commit 11c3629

File tree

2 files changed

+129
-117
lines changed

2 files changed

+129
-117
lines changed

phpsec.class.php

Lines changed: 1 addition & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public static function load($class) {
3636
'phpsecOtp' => 'phpsec.otp.php',
3737
'phpsecStore' => 'phpsec.store.php',
3838
'phpsecToken' => 'phpsec.token.php',
39+
'phpsecPw' => 'phpsec.pw.php',
3940
'phpsecStoreFilesystem' => 'phpsec.store.filesystem.php',
4041
);
4142

@@ -247,121 +248,4 @@ public static function genUid($length = 50) {
247248
$randLength = $length-strlen($timeStamp);
248249
return $timeStamp.phpsecRand::str($randLength);
249250
}
250-
251-
/**
252-
* Create a hashed version of a password, safe for storage in a database.
253-
* This function return a json encodeed array that can be stored directly
254-
* in a database. The array has the following layout:
255-
* array(
256-
* 'hash' => The hash created from the password and a salt.
257-
* 'salt' => The salt that was used along with the password to create the hash.
258-
* 'nse?algo' => The hashing algorythm used.
259-
* 'injection' => How the salt was injected into the password.
260-
* )
261-
* The following injection methods exists:
262-
* before: The salt is placed diectly in front of the password, without using any
263-
* seperation characters.
264-
* after: The salt is placed directly after the password without any seperation
265-
* characters.
266-
*
267-
* @param string $password
268-
* The password to hash.
269-
*
270-
* @return string
271-
* Returns a json encoded array containing the password hash, salt and
272-
* some meta data.
273-
*/
274-
public static function pwHash($password) {
275-
$salt = self::genUid();
276-
$injected = self::pwInject($password, $salt);
277-
$hash = hash(self::HASH_TYPE, $injected);
278-
279-
$return = array(
280-
'hash' => $hash,
281-
'salt' => $salt,
282-
'algo' => self::HASH_TYPE,
283-
);
284-
return json_encode($return);
285-
}
286-
287-
/**
288-
* Validate a user-supplied password against a stored password saved
289-
* using the pwHash() method.
290-
*
291-
* @param string $password
292-
* The password supplied by the user in the login form.
293-
*
294-
* @param string $dbPassword
295-
* The json string fetched from the database, in the exact format
296-
* as created by pwHash().
297-
*
298-
* @return boolean
299-
* True on password match, false otherwise.
300-
*/
301-
public static function pwCheck($password, $dbPassword) {
302-
/**
303-
* Unserialize registerd password array and validate it to ensure
304-
* we got a valid array.
305-
*/
306-
$data = json_decode($dbPassword, true);
307-
if(isset($data['algo']) && sizeof($data) == 3) {
308-
/**
309-
* Ok, we are pretty sure this is good stuff. Now inject the salt
310-
* into the user supplied password, to see if it matches the registerd
311-
* data from $dbPassword.
312-
*/
313-
$pwInjected = self::pwInject($password, $data['salt']);
314-
/* Create a hash and see if it matches. */
315-
if(hash($data['algo'], $pwInjected) == $data['hash']) {
316-
return true;
317-
}
318-
} else {
319-
/* Invalid array supplied. */
320-
self::error('Invalid data supplied. Expected serialized array as returned by pwHash()');
321-
}
322-
return false;
323-
}
324-
325-
/**
326-
* Check the age of a salted password.
327-
*
328-
* @param string $dbPassword
329-
* The json string fetched from the database, in the exact format
330-
* as created by pwHash().
331-
*
332-
* @return integer
333-
* Age of password in seconds.
334-
*/
335-
public static function pwAge($dbPassword) {
336-
$data = json_decode($dbPassword, true);
337-
if(isset($data['salt'])) {
338-
$date = substr($data['salt'], 0, 22);
339-
return gmdate('U') - strtotime($date);
340-
} else {
341-
/* Invalid array supplied. */
342-
self::error('Invalid data supplied. Expected serialized array as returned by pwHash()');
343-
}
344-
return false;
345-
}
346-
347-
/**
348-
* Inject a salt into a password to create the string to be hashed.
349-
*
350-
* @param string $password
351-
* Plain-text password.
352-
*
353-
* @param string $salt
354-
* Well, the salt to inject into the password.
355-
*
356-
* @return string
357-
* Returns the salted password, ready to be hashed.
358-
*
359-
*/
360-
private static function pwInject($password, $salt) {
361-
$hex = hexdec(substr(hash(self::HASH_TYPE, $password), 0, 1));
362-
$len = strlen($password);
363-
$pos = floor($hex*($len/16));
364-
365-
return substr($password, 0, $pos).$salt.substr($password, $pos);
366-
}
367251
}

phpsec/phpsec.pw.php

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
/**
3+
phpSec - A PHP security library
4+
5+
@author Audun Larsen <larsen@xqus.com>
6+
@copyright Copyright (c) Audun Larsen, 2011
7+
@link https://github.com/xqus/phpSec
8+
@license http://opensource.org/licenses/mit-license.php The MIT License
9+
@package phpSec
10+
*/
11+
12+
class phpsecPw {
13+
/**
14+
* Create a hashed version of a password, safe for storage in a database.
15+
* This function return a json encodeed array that can be stored directly
16+
* in a database. The array has the following layout:
17+
* array(
18+
* 'hash' => The hash created from the password and a salt.
19+
* 'salt' => The salt that was used along with the password to create the hash.
20+
* 'algo' => The hashing algorythm used.
21+
* )
22+
* The following injection methods exists:
23+
* before: The salt is placed diectly in front of the password, without using any
24+
* seperation characters.
25+
* after: The salt is placed directly after the password without any seperation
26+
* characters.
27+
*
28+
* @param string $password
29+
* The password to hash.
30+
*
31+
* @return string
32+
* Returns a json encoded array containing the password hash, salt and
33+
* some meta data.
34+
*/
35+
public static function hash($password) {
36+
$salt = phpsec::genUid();
37+
$injected = self::inject($password, $salt);
38+
$hash = hash(phpsec::HASH_TYPE, $injected);
39+
40+
$return = array(
41+
'hash' => $hash,
42+
'salt' => $salt,
43+
'algo' => phpsec::HASH_TYPE,
44+
);
45+
return json_encode($return);
46+
}
47+
48+
/**
49+
* Validate a user-supplied password against a stored password saved
50+
* using the phpsecPw::hash() method.
51+
*
52+
* @param string $password
53+
* The password supplied by the user in the login form.
54+
*
55+
* @param string $dbPassword
56+
* The json string fetched from the database, in the exact format
57+
* as created by pwHash().
58+
*
59+
* @return boolean
60+
* True on password match, false otherwise.
61+
*/
62+
public static function check($password, $dbPassword) {
63+
/**
64+
* Unserialize registerd password array and validate it to ensure
65+
* we got a valid array.
66+
*/
67+
$data = json_decode($dbPassword, true);
68+
if(isset($data['algo']) && sizeof($data) == 3) {
69+
/**
70+
* Ok, we are pretty sure this is good stuff. Now inject the salt
71+
* into the user supplied password, to see if it matches the registerd
72+
* data from $dbPassword.
73+
*/
74+
$pwInjected = self::inject($password, $data['salt']);
75+
/* Create a hash and see if it matches. */
76+
if(hash($data['algo'], $pwInjected) == $data['hash']) {
77+
return true;
78+
}
79+
} else {
80+
/* Invalid array supplied. */
81+
self::error('Invalid data supplied. Expected serialized array as returned by pwHash()');
82+
}
83+
return false;
84+
}
85+
86+
/**
87+
* Check the age of a salted password.
88+
*
89+
* @param string $dbPassword
90+
* The json string fetched from the database, in the exact format
91+
* as created by phpsecPw::hash().
92+
*
93+
* @return integer
94+
* Age of password in seconds.
95+
*/
96+
public static function age($dbPassword) {
97+
$data = json_decode($dbPassword, true);
98+
if(isset($data['salt'])) {
99+
$date = substr($data['salt'], 0, 22);
100+
return gmdate('U') - strtotime($date);
101+
} else {
102+
/* Invalid array supplied. */
103+
self::error('Invalid data supplied. Expected serialized array as returned by pwHash()');
104+
}
105+
return false;
106+
}
107+
108+
/**
109+
* Inject a salt into a password to create the string to be hashed.
110+
*
111+
* @param string $password
112+
* Plain-text password.
113+
*
114+
* @param string $salt
115+
* Well, the salt to inject into the password.
116+
*
117+
* @return string
118+
* Returns the salted password, ready to be hashed.
119+
*
120+
*/
121+
private static function inject($password, $salt) {
122+
$hex = hexdec(substr(hash(phpsec::HASH_TYPE, $password), 0, 1));
123+
$len = strlen($password);
124+
$pos = floor($hex*($len/16));
125+
126+
return substr($password, 0, $pos).$salt.substr($password, $pos);
127+
}
128+
}

0 commit comments

Comments
 (0)