add methods to decrypt return data from router
[GitHub/Stricted/speedport-hybrid-php-api.git] / CryptLib / Password / Implementation / APR1.php
CommitLineData
14d4f286
S
1<?php
2/**
3 * The APR1 password hashing implementation
4 *
5 * Use this class to generate and validate APR1 password hashes. APR1 hashes
6 * are used primarrily by Apache for .htaccess password storage.
7 *
8 * PHP version 5.3
9 *
10 * @see http://httpd.apache.org/docs/2.2/misc/password_encryptions.html
11 * @category PHPCryptLib
12 * @package Password
13 * @subpackage Implementation
14 * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
15 * @copyright 2011 The Authors
16 * @license http://www.opensource.org/licenses/mit-license.html MIT License
17 * @version Build @@version@@
18 */
19
20namespace CryptLib\Password\Implementation;
21
22use CryptLib\Random\Factory as RandomFactory;
23
24/**
25 * The APR1 password hashing implementation
26 *
27 * Use this class to generate and validate APR1 password hashes. APR1 hashes
28 * are used primarrily by Apache for .htaccess password storage.
29 *
30 * @see http://httpd.apache.org/docs/2.2/misc/password_encryptions.html
31 * @category PHPCryptLib
32 * @package Password
33 * @subpackage Implementation
34 * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
35 */
36class APR1 implements \CryptLib\Password\Password {
37
38 /**
39 * @var Generator The random generator to use for seeds
40 */
41 protected $generator = null;
42
43 /**
44 * @var Hash The hash function to use (MD5)
45 */
46 protected $hash = null;
47
48 /**
49 * @var int The number of iterations to perform (1000 for APR1)
50 */
51 protected $iterations = 1000;
52
53 /**
54 * Determine if the hash was made with this method
55 *
56 * @param string $hash The hashed data to check
57 *
58 * @return boolean Was the hash created by this method
59 */
60 public static function detect($hash) {
61 return strncmp($hash, '$apr1$', 6) === 0;
62 }
63
64 /**
65 * Return the prefix used by this hashing method
66 *
67 * @return string The prefix used
68 */
69 public static function getPrefix() {
70 return '$apr1$';
71 }
72
73 /**
74 * Load an instance of the class based upon the supplied hash
75 *
76 * @param string $hash The hash to load from
77 *
78 * @return Password the created instance
79 * @throws InvalidArgumentException if the hash wasn't created here
80 */
81 public static function loadFromHash($hash) {
82 if (!static::detect($hash)) {
83 throw new \InvalidArgumentException('Hash Not Created Here');
84 }
85 return new static;
86 }
87
88 /**
89 * Build a new instance
90 *
91 * @param Generator $generator The random generator to use for seeds
92 *
93 * @return void
94 */
95 public function __construct(
96 \CryptLib\Random\Generator $generator = null
97 ) {
98 if (is_null($generator)) {
99 $random = new RandomFactory();
100 $generator = $random->getMediumStrengthGenerator();
101 }
102 $this->generator = $generator;
103 }
104
105 /**
106 * Create a password hash for a given plain text password
107 *
108 * @param string $password The password to hash
109 *
110 * @return string The formatted password hash
111 */
112 public function create($password) {
113 $salt = $this->to64($this->generator->generateInt(0, PHP_INT_MAX), 8);
114 return $this->hash($password, $salt, $this->iterations);
115 }
116
117 /**
118 * Verify a password hash against a given plain text password
119 *
120 * @param string $password The password to hash
121 * @param string $hash The supplied ahsh to validate
122 *
123 * @return boolean Does the password validate against the hash
124 */
125 public function verify($password, $hash) {
126 $bits = explode('$', $hash);
127 if (!isset($bits[3]) || $bits[1] != 'apr1') {
128 return false;
129 }
130 $test = $this->hash($password, $bits[2], $this->iterations);
131 return $test == $hash;
132 }
133
134 /**
135 * Perform the hashing of the password
136 *
137 * @param string $password The plain text password to hash
138 * @param string $salt The 8 byte salt to use
139 * @param int $iterations The number of iterations to use
140 *
141 * @return string The hashed password
142 */
143 protected function hash($password, $salt, $iterations) {
144 $len = strlen($password);
145 $text = $password . '$apr1$' . $salt;
146 $bin = md5($password.$salt.$password, true);
147 for ($i = $len; $i > 0; $i -= 16) {
148 $text .= substr($bin, 0, min(16, $i));
149 }
150 for ($i = $len; $i > 0; $i >>= 1) {
151 $text .= ($i & 1) ? chr(0) : $password[0];
152 }
153 $bin = $this->iterate($text, $iterations, $salt, $password);
154 return $this->convertToHash($bin, $salt);
155 }
156
157 protected function iterate($text, $iterations, $salt, $password) {
158 $bin = md5($text, true);
159 for ($i = 0; $i < $iterations; $i++) {
160 $new = ($i & 1) ? $password : $bin;
161 if ($i % 3) {
162 $new .= $salt;
163 }
164 if ($i % 7) {
165 $new .= $password;
166 }
167 $new .= ($i & 1) ? $bin : $password;
168 $bin = md5($new, true);
169 }
170 return $bin;
171 }
172
173 protected function convertToHash($bin, $salt) {
174 $tmp = '$apr1$'.$salt.'$';
175 $tmp .= $this->to64(
176 (ord($bin[0])<<16) | (ord($bin[6])<<8) | ord($bin[12]),
177 4
178 );
179 $tmp .= $this->to64(
180 (ord($bin[1])<<16) | (ord($bin[7])<<8) | ord($bin[13]),
181 4
182 );
183 $tmp .= $this->to64(
184 (ord($bin[2])<<16) | (ord($bin[8])<<8) | ord($bin[14]),
185 4
186 );
187 $tmp .= $this->to64(
188 (ord($bin[3])<<16) | (ord($bin[9])<<8) | ord($bin[15]),
189 4
190 );
191 $tmp .= $this->to64(
192 (ord($bin[4])<<16) | (ord($bin[10])<<8) | ord($bin[5]),
193 4
194 );
195 $tmp .= $this->to64(
196 ord($bin[11]),
197 2
198 );
199 return $tmp;
200 }
201
202 /**
203 * Convert the input number to a base64 number of the specified size
204 *
205 * @param int $num The number to convert
206 * @param int $size The size of the result string
207 *
208 * @return string The converted representation
209 */
210 protected function to64($num, $size) {
211 static $seed = '';
212 if (empty($seed)) {
213 $seed = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
214 'abcdefghijklmnopqrstuvwxyz';
215 }
216 $result = '';
217 while (--$size >= 0) {
218 $result .= $seed[$num & 0x3f];
219 $num >>= 6;
220 }
221 return $result;
222 }
223
224}