blob: b2170103eeb88eb3f7d97ab4a04688c1b081ace5 [file] [log] [blame]
Andrey Andreev9a152a92014-02-18 16:29:53 +02001<?php
2/**
3 * CodeIgniter
4 *
5 * An open source application development framework for PHP 5.2.4 or newer
6 *
7 * NOTICE OF LICENSE
8 *
9 * Licensed under the Open Software License version 3.0
10 *
11 * This source file is subject to the Open Software License (OSL 3.0) that is
12 * bundled with this package in the files license.txt / license.rst. It is
13 * also available through the world wide web at this URL:
14 * http://opensource.org/licenses/OSL-3.0
15 * If you did not receive a copy of the license and are unable to obtain it
16 * through the world wide web, please send an email to
17 * licensing@ellislab.com so we can send you a copy immediately.
18 *
19 * @package CodeIgniter
20 * @author EllisLab Dev Team
21 * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
22 * @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
23 * @link http://codeigniter.com
24 * @since Version 3.0
25 * @filesource
26 */
27defined('BASEPATH') OR exit('No direct script access allowed');
28
29/**
30 * PHP ext/hash compatibility package
31 *
32 * @package CodeIgniter
33 * @subpackage CodeIgniter
34 * @category Compatibility
35 * @author Andrey Andreev
36 * @link http://codeigniter.com/user_guide/
37 * @link http://php.net/hash
38 */
39
40// ------------------------------------------------------------------------
41
Andrey Andreeva5621b82014-05-09 11:23:08 +030042if (is_php('5.6'))
43{
44 return;
45}
46
47// ------------------------------------------------------------------------
48
49if ( ! function_exists('hash_equals'))
50{
51 /**
52 * hash_equals()
53 *
54 * @link http://php.net/hash_equals
55 * @param string $known_string
56 * @param string $user_string
57 * @return bool
58 */
59 function hash_equals($known_string, $user_string)
60 {
61 if ( ! is_string($known_string))
62 {
63 trigger_error('hash_equals(): Expected known_string to be a string, '.strtolower(gettype($known_string)).' given', E_USER_WARNING);
64 return FALSE;
65 }
66 elseif ( ! is_string($user_string))
67 {
68 trigger_error('hash_equals(): Expected user_string to be a string, '.strtolower(gettype($user_string)).' given', E_USER_WARNING);
69 return FALSE;
70 }
71 elseif (($length = strlen($known_string)) !== strlen($user_string))
72 {
73 return FALSE;
74 }
75
76 $diff = 0;
77 for ($i = 0; $i < $length; $i++)
78 {
79 $diff |= ord($known_string[$i]) ^ ord($user_string[$i]);
80 }
81
82 return ($diff === 0);
83 }
84}
85
86// ------------------------------------------------------------------------
87
Andrey Andreev9a152a92014-02-18 16:29:53 +020088if (is_php('5.5'))
89{
90 return;
91}
92
93// ------------------------------------------------------------------------
94
95if ( ! function_exists('hash_pbkdf2'))
96{
97 /**
98 * hash_pbkdf2()
99 *
100 * @link http://php.net/hash_pbkdf2
101 * @param string $algo
102 * @param string $password
103 * @param string $salt
104 * @param int $iterations
105 * @param int $length
106 * @param bool $raw_output
107 * @return string
108 */
109 function hash_pbkdf2($algo, $password, $salt, $iterations, $length = 0, $raw_output = FALSE)
110 {
111 if ( ! in_array($algo, hash_algos(), TRUE))
112 {
113 trigger_error('hash_pbkdf2(): Unknown hashing algorithm: '.$algo, E_USER_WARNING);
114 return FALSE;
115 }
116
117 if (($type = gettype($iterations)) !== 'integer')
118 {
119 if ($type === 'object' && method_exists($iterations, '__toString'))
120 {
121 $iterations = (string) $iterations;
122 }
123
124 if (is_string($iterations) && is_numeric($iterations))
125 {
126 $iterations = (int) $iterations;
127 }
128 else
129 {
130 trigger_error('hash_pbkdf2() expects parameter 4 to be long, '.$type.' given', E_USER_WARNING);
131 return NULL;
132 }
133 }
134
135 if ($iterations < 1)
136 {
137 trigger_error('hash_pbkdf2(): Iterations must be a positive integer: '.$iterations, E_USER_WARNING);
138 return FALSE;
139 }
140
141 if (($type = gettype($length)) !== 'integer')
142 {
143 if ($type === 'object' && method_exists($length, '__toString'))
144 {
145 $length = (string) $length;
146 }
147
148 if (is_string($length) && is_numeric($length))
149 {
150 $length = (int) $length;
151 }
152 else
153 {
154 trigger_error('hash_pbkdf2() expects parameter 5 to be long, '.$type.' given', E_USER_WARNING);
155 return NULL;
156 }
157 }
158
159 if ($length < 0)
160 {
161 trigger_error('hash_pbkdf2(): Length must be greater than or equal to 0: '.$length, E_USER_WARNING);
162 return FALSE;
163 }
164
165 $hash_length = strlen(hash($algo, NULL, TRUE));
166 if (empty($length))
167 {
168 $length = $hash_length;
169 }
170
171 $hash = '';
172 // Note: Blocks are NOT 0-indexed
173 for ($bc = ceil($length / $hash_length), $bi = 1; $bi <= $bc; $bi++)
174 {
175 $key = $derived_key = hash_hmac($algo, $salt.pack('N', $bi), $password, TRUE);
176 for ($i = 1; $i < $iterations; $i++)
177 {
178 $derived_key ^= $key = hash_hmac($algo, $key, $password, TRUE);
179 }
180
181 $hash .= $derived_key;
182 }
183
184 // This is not RFC-compatible, but we're aiming for natural PHP compatibility
185 return substr($raw_output ? $hash : bin2hex($hash), 0, $length);
186 }
187}
188
189/* End of file hash.php */
190/* Location: ./system/core/compat/hash.php */