add methods to decrypt return data from router
[GitHub/Stricted/speedport-hybrid-php-api.git] / CryptLib / Password / Implementation / Blowfish.php
CommitLineData
14d4f286
S
1<?php
2/**
3 * The Blowfish password hashing implementation
4 *
5 * Use this class to generate and validate Blowfish password hashes.
6 *
7 * PHP version 5.3
8 *
9 * @category PHPCryptLib
10 * @package Password
11 * @subpackage Implementation
12 * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
13 * @copyright 2011 The Authors
14 * @license http://www.opensource.org/licenses/mit-license.html MIT License
15 * @version Build @@version@@
16 */
17
18namespace CryptLib\Password\Implementation;
19
20use CryptLib\Random\Factory as RandomFactory;
21
22/**
23 * The Blowfish password hashing implementation
24 *
25 * Use this class to generate and validate Blowfish password hashes.
26 *
27 * @category PHPCryptLib
28 * @package Password
29 * @subpackage Implementation
30 * @author Anthony Ferrara <ircmaxell@ircmaxell.com>
31 */
32class Blowfish implements \CryptLib\Password\Password {
33
34 /**
35 * @var Generator The random generator to use for seeds
36 */
37 protected $generator = null;
38
39 /**
40 * @var int The number of iterations to perform (base 2)
41 */
42 protected $iterations = 10;
43
44 /**
45 * Determine if the hash was made with this method
46 *
47 * @param string $hash The hashed data to check
48 *
49 * @return boolean Was the hash created by this method
50 */
51 public static function detect($hash) {
52 static $regex = '/^\$2[ay]\$(0[4-9]|[1-2][0-9]|3[0-1])\$[a-zA-Z0-9.\/]{53}/';
53 return 1 == preg_match($regex, $hash);
54 }
55
56 /**
57 * Return the prefix used by this hashing method
58 *
59 * @return string The prefix used
60 */
61 public static function getPrefix() {
62 if (version_compare(PHP_VERSION, '5.3.7') >= 0) {
63 return '$2y$';
64 } else {
65 return '$2a$';
66 }
67 }
68
69 /**
70 * Load an instance of the class based upon the supplied hash
71 *
72 * @param string $hash The hash to load from
73 *
74 * @return Password the created instance
75 * @throws InvalidArgumentException if the hash wasn't created here
76 */
77 public static function loadFromHash($hash) {
78 if (!static::detect($hash)) {
79 throw new \InvalidArgumentException('Hash Not Created Here');
80 }
81 list(, , $iterations) = explode('$', $hash, 4);
82 return new static((int) $iterations);
83 }
84
85 /**
86 * Build a new instance
87 *
88 * @param int $iterations The number of times to iterate the hash
89 * @param Generator $generator The random generator to use for seeds
90 *
91 * @return void
92 */
93 public function __construct(
94 $iterations = 8,
95 \CryptLib\Random\Generator $generator = null
96 ) {
97 if ($iterations > 31 || $iterations < 4) {
98 throw new \InvalidArgumentException('Invalid Iteration Count Supplied');
99 }
100 $this->iterations = $iterations;
101 if (is_null($generator)) {
102 $random = new RandomFactory();
103 $generator = $random->getMediumStrengthGenerator();
104 }
105 $this->generator = $generator;
106 }
107
108 /**
109 * Create a password hash for a given plain text password
110 *
111 * @param string $password The password to hash
112 *
113 * @return string The formatted password hash
114 */
115 public function create($password) {
116 /**
117 * Check for security flaw in the bcrypt implementation used by crypt()
118 * @see http://php.net/security/crypt_blowfish.php
119 */
120 $match = preg_match('/[\x80-\xFF]/', $password);
121 if (version_compare(PHP_VERSION, '5.3.7', '<') && $match) {
122 throw new \RuntimeException(
123 'The bcrypt implementation used by PHP contains a security flaw ' .
124 'for password with 8-bit character. We suggest to upgrade to ' .
125 'PHP 5.3.7+ or use passwords with only 7-bit characters'
126 );
127 }
128 $salt = $this->to64($this->generator->generate(16));
129 $prefix = static::getPrefix();
130 $prefix .= str_pad($this->iterations, 2, '0', STR_PAD_LEFT);
131 $saltstring = $prefix . '$' . $salt;
132 $result = crypt($password, $saltstring);
133 if ($result[0] == '*') {
134 //@codeCoverageIgnoreStart
135 throw new \RuntimeException('Password Could Not Be Created');
136 //@codeCoverageIgnoreEnd
137 }
138 return $result;
139 }
140
141 /**
142 * Verify a password hash against a given plain text password
143 *
144 * @param string $password The password to hash
145 * @param string $hash The supplied ahsh to validate
146 *
147 * @return boolean Does the password validate against the hash
148 */
149 public function verify($password, $hash) {
150 if (!static::detect($hash)) {
151 throw new \InvalidArgumentException(
152 'The hash was not created here, we cannot verify it'
153 );
154 }
155 $test = crypt($password, $hash);
156 return $test == $hash;
157 }
158
159 /**
160 * Convert the input number to a base64 number of the specified size
161 *
162 * @param int $input The number to convert
163 *
164 * @return string The converted representation
165 */
166 protected function to64($input) {
167 static $itoa = null;
168 if (empty($itoa)) {
169 $itoa = './ABCDEFGHIJKLMNOPQRSTUVWXYZ'
170 . 'abcdefghijklmnopqrstuvwxyz0123456789';
171 }
172 $output = '';
173 $size = strlen($input);
174 $ictr = 0;
175 do {
176 $cval1 = ord($input[$ictr++]);
177 $output .= $itoa[$cval1 >> 2];
178 $cval1 = ($cval1 & 0x03) << 4;
179 if ($ictr >= $size) {
180 $output .= $itoa[$cval1];
181 break;
182 }
183 $cval2 = ord($input[$ictr++]);
184 $cval1 |= $cval2 >> 4;
185 $output .= $itoa[$cval1];
186 $cval1 = ($cval2 & 0x0f) << 2;
187 $cval2 = ord($input[$ictr++]);
188 $cval1 |= $cval2 >> 6;
189 $output .= $itoa[$cval1];
190 $output .= $itoa[$cval2 & 0x3f];
191 } while (true);
192 return $output;
193 }
194
195}