forked from arzzcom/iModule.core
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathHash.class.php
More file actions
125 lines (106 loc) · 3.77 KB
/
Hash.class.php
File metadata and controls
125 lines (106 loc) · 3.77 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
<?php
/**
* 이 파일은 MoimzTools 의 일부입니다. (https://www.moimz.com)
*
* 패스워드를 저장하기 위한 SALT 기반 해시를 생성하거나, 패스워드를 검증한다.
*
* @file /classes/Hash.class.php
* @author Arzz
* @license MIT License
* @version 1.0.0
* @modified 2018. 3. 18.
*/
define('PBKDF2_COMPAT_HASH_ALGORITHM','SHA256');
define('PBKDF2_COMPAT_ITERATIONS',12000);
define('PBKDF2_COMPAT_SALT_BYTES',24);
define('PBKDF2_COMPAT_HASH_BYTES',24);
class Hash {
function password_hash($password,$force_compat=false) {
if (function_exists('mcrypt_create_iv')) {
$salt = base64_encode(mcrypt_create_iv(PBKDF2_COMPAT_SALT_BYTES,MCRYPT_DEV_URANDOM));
} elseif (file_exists('/dev/urandom') && $fp = @fopen('/dev/urandom','r')) {
$salt = base64_encode(fread($fp,PBKDF2_COMPAT_SALT_BYTES));
} else {
$salt = '';
for ($i=0;$i<PBKDF2_COMPAT_SALT_BYTES;$i+= 2) {
$salt.= pack('S',mt_rand(0,65535));
}
$salt = base64_encode(substr($salt,0,PBKDF2_COMPAT_SALT_BYTES));
}
$algo = strtolower(PBKDF2_COMPAT_HASH_ALGORITHM);
$iterations = PBKDF2_COMPAT_ITERATIONS;
if ($force_compat || !function_exists('hash_algos') || !in_array($algo,hash_algos())) {
$algo = false;
$iterations = round($iterations / 5);
}
$pbkdf2 = $this->pbkdf2_default($algo,$password,$salt,$iterations,PBKDF2_COMPAT_HASH_BYTES);
$prefix = $algo ? $algo : 'sha1';
return $salt.':'.base64_encode($pbkdf2);
}
function password_validate($password,$hash) {
$params = explode(':',$hash);
if (count($params) < 2) return false;
$pbkdf2 = base64_decode($params[1]);
$pbkdf2_check = $this->pbkdf2_default(PBKDF2_COMPAT_HASH_ALGORITHM,$password,$params[0],PBKDF2_COMPAT_ITERATIONS,strlen($pbkdf2));
return $this->slow_equals($pbkdf2,$pbkdf2_check);
}
function slow_equals($a,$b) {
$diff = strlen($a) ^ strlen($b);
for($i = 0; $i < strlen($a) && $i < strlen($b); $i++) {
$diff |= ord($a[$i]) ^ ord($b[$i]);
}
return $diff === 0;
}
function pbkdf2_default($algo,$password,$salt,$count,$key_length) {
if ($count <= 0 || $key_length <= 0) {
trigger_error('PBKDF2 ERROR: Invalid parameters.',E_USER_ERROR);
}
if (!$algo) return $this->pbkdf2_fallback($password,$salt,$count,$key_length);
$algo = strtolower($algo);
if (!function_exists('hash_algos') || !in_array($algo,hash_algos())) {
if ($algo === 'sha1') {
return $this->pbkdf2_fallback($password,$salt,$count,$key_length);
} else {
trigger_error('PBKDF2 ERROR: Hash algorithm not supported.',E_USER_ERROR);
}
}
if (function_exists('hash_pbkdf2')) {
return hash_pbkdf2($algo,$password,$salt,$count,$key_length,true);
}
$hash_length = strlen(hash($algo,'',true));
$block_count = ceil($key_length / $hash_length);
$output = '';
for ($i=1;$i<=$block_count;$i++) {
$last = $salt.pack('N',$i);
$last = $xorsum = hash_hmac($algo,$last,$password,true);
for ($j=1;$j<$count;$j++) {
$xorsum ^= ($last = hash_hmac($algo,$last,$password,true));
}
$output.= $xorsum;
}
return substr($output,0,$key_length);
}
function pbkdf2_fallback($password,$salt,$count,$key_length) {
$hash_length = 20;
$block_count = ceil($key_length / $hash_length);
if (strlen($password) > 64) {
$password = str_pad(sha1($password,true),64,chr(0));
} else {
$password = str_pad($password,64,chr(0));
}
$opad = str_repeat(chr(0x5C),64) ^ $password;
$ipad = str_repeat(chr(0x36),64) ^ $password;
$output = '';
for ($i=1;$i<=$block_count;$i++) {
$last = $salt . pack('N',$i);
$xorsum = $last = pack('H*',sha1($opad.pack('H*',sha1($ipad.$last))));
for ($j=1;$j<$count;$j++) {
$last = pack('H*',sha1($opad.pack('H*',sha1($ipad.$last))));
$xorsum ^= $last;
}
$output.= $xorsum;
}
return substr($output,0,$key_length);
}
}
?>