add methods to decrypt return data from router
[GitHub/Stricted/speedport-hybrid-php-api.git] / CryptLib / Password / Implementation / PBKDF.php
1 <?php
2 /**
3 * The PBKDF based password hashing implementation
4 *
5 * Use this class to generate and validate PBKDF hashed passwords.
6 *
7 * PHP version 5.3
8 *
9 * @see http://httpd.apache.org/docs/2.2/misc/password_encryptions.html
10 * @category PHPCryptLib
11 * @package Password
12 * @subpackage Implementation
13 * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
14 * @copyright 2011 The Authors
15 * @license http://www.opensource.org/licenses/mit-license.html MIT License
16 * @version Build @@version@@
17 */
18
19 namespace CryptLib\Password\Implementation;
20
21 use CryptLib\Key\Factory as KeyFactory;
22 use CryptLib\Random\Factory as RandomFactory;
23 use CryptLib\Key\Derivation\PBKDF\PBKDF2 as PBKDF2;
24
25 /**
26 * The PBKDF based password hashing implementation
27 *
28 * Use this class to generate and validate PBKDF hashed passwords.
29 *
30 * PHP version 5.3
31 *
32 * @see http://httpd.apache.org/docs/2.2/misc/password_encryptions.html
33 * @category PHPCryptLib
34 * @package Password
35 * @subpackage Implementation
36 * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
37 */
38 class PBKDF implements \CryptLib\Password\Password {
39
40 /**
41 * @var PBKDF The PBKDF derivation implementation to use for this instance
42 */
43 protected $derivation = null;
44
45 /**
46 * @var Generator The Random Number Generator to use for making salts
47 */
48 protected $generator = null;
49
50 /**
51 * @var int The number of iterations to perform on the password
52 */
53 protected $iterations = 5000;
54
55 /**
56 * @var int The length in bytes of the generated password hash
57 */
58 protected $size = 40;
59
60 /**
61 * Determine if the hash was made with this method
62 *
63 * @param string $hash The hashed data to check
64 *
65 * @return boolean Was the hash created by this method
66 */
67 public static function detect($hash) {
68 return strncmp($hash, '$pbkdf$', 7) === 0;
69 }
70
71 /**
72 * Return the prefix used by this hashing method
73 *
74 * @return string The prefix used
75 */
76 public static function getPrefix() {
77 return '$pbkdf$';
78 }
79
80 /**
81 * Load an instance of the class based upon the supplied hash
82 *
83 * @param string $hash The hash to load from
84 *
85 * @return Password the created instance
86 * @throws InvalidArgumentException if the hash wasn't created here
87 */
88 public static function loadFromHash($hash) {
89 if (!static::detect($hash)) {
90 throw new \InvalidArgumentException('Hash Not Created Here');
91 }
92 $parts = explode('$', $hash);
93 if (count($parts) != 7) {
94 throw new \InvalidArgumentException('Hash Not Created Here');
95 }
96 $signature = $parts[2];
97 $factory = new KeyFactory();
98 $hash = $factory->getPBKDFFromSignature($signature);
99 $iterations = $parts[3];
100 $size = $parts[4];
101 return new static($hash, $size, $iterations);
102 }
103
104 /**
105 * Build a new instance of the PBKDF password class
106 *
107 * @param PBKDF $derivation The derivation class to use
108 * @param int $size The size of hash to generate
109 * @param int $iterations The number of iterations to perform
110 * @param Generator $generator The Random Generator to use
111 *
112 * @return void;
113 */
114 public function __construct(
115 \CryptLib\Key\Derivation\PBKDF $derivation = null,
116 $size = 40,
117 $iterations = 5000,
118 \CryptLib\Random\Generator $generator = null
119 ) {
120 if (is_null($derivation)) {
121 $derivation = new PBKDF2();
122 }
123 $this->derivation = $derivation;
124 $this->size = $size < 40 ? 40 : (int) $size;
125 $this->iterations = $iterations > 0 ? (int) $iterations : 1;
126 if (is_null($generator)) {
127 $factory = new RandomFactory;
128 $generator = $factory->getMediumStrengthGenerator();
129 }
130 $this->generator = $generator;
131 }
132
133 /**
134 * Create a password hash for a given plain text password
135 *
136 * @param string $password The password to hash
137 *
138 * @return string The formatted password hash
139 */
140 public function create($password) {
141 $size = $this->size - 8; // remove size of stored bits
142 $saltSize = floor($size / 5); //Use 20% of the size for the salt
143 $hashSize = $size - $saltSize;
144 $salt = $this->generator->generate($saltSize);
145 return $this->hash($password, $salt, $this->iterations, $hashSize);
146 }
147
148 /**
149 * Verify a password hash against a given plain text password
150 *
151 * @param string $password The password to hash
152 * @param string $hash The supplied ahsh to validate
153 *
154 * @return boolean Does the password validate against the hash
155 */
156 public function verify($password, $hash) {
157 if (strlen($hash) <= 16 || strpos($hash, '$') === false) {
158 return false;
159 }
160 $parts = explode('$', $hash);
161 if (count($parts) != 7) {
162 return false;
163 } elseif ($parts[2] != $this->derivation->getSignature()) {
164 return false;
165 }
166 $iterations = $parts[3];
167 $size = $parts[4];
168 $salt = base64_decode($parts[5]);
169 return $this->hash($password, $salt, $iterations, $size) == $hash;
170 }
171
172 /**
173 * Perform the hashing of the password
174 *
175 * @param string $password The plain text password to hash
176 * @param string $salt The 8 byte salt to use
177 * @param int $iterations The number of iterations to use
178 *
179 * @return string The hashed password
180 */
181 protected function hash($password, $salt, $iterations, $size) {
182 $bit = $this->derivation->derive($password, $salt, $iterations, $size);
183 $sig = $this->derivation->getSignature();
184 $sig = '$pbkdf$' . $sig . '$' . $iterations . '$' . $size;
185 return $sig . '$' . base64_encode($salt) . '$' . base64_encode($bit);
186 }
187
188 }