1 <?php
2 /**
3 * @package Joomla.Platform
4 * @subpackage Crypt
5 *
6 * @copyright Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE
8 */
9
10 defined('JPATH_PLATFORM') or die;
11
12 /**
13 * Joomla Platform Password Crypter
14 *
15 * @since 12.2
16 * @deprecated 4.0 Use PHP 5.5's native password hashing API
17 */
18 class JCryptPasswordSimple implements JCryptPassword
19 {
20 /**
21 * @var integer The cost parameter for hashing algorithms.
22 * @since 12.2
23 * @deprecated 4.0 Use PHP 5.5's native password hashing API
24 */
25 protected $cost = 10;
26
27 /**
28 * @var string The default hash type
29 * @since 12.3
30 * @deprecated 4.0 Use PHP 5.5's native password hashing API
31 */
32 protected $defaultType = '$2y$';
33
34 /**
35 * Creates a password hash
36 *
37 * @param string $password The password to hash.
38 * @param string $type The hash type.
39 *
40 * @return mixed The hashed password or false if the password is too long.
41 *
42 * @since 12.2
43 * @throws InvalidArgumentException
44 * @deprecated 4.0 Use PHP 5.5's native password hashing API
45 */
46 public function create($password, $type = null)
47 {
48 if (empty($type))
49 {
50 $type = $this->defaultType;
51 }
52
53 switch ($type)
54 {
55 case '$2a$':
56 case JCryptPassword::BLOWFISH:
57
58 $type = '$2a$';
59
60 if (JCrypt::hasStrongPasswordSupport())
61 {
62 $type = '$2y$';
63 }
64
65 $salt = $type . str_pad($this->cost, 2, '0', STR_PAD_LEFT) . '$' . $this->getSalt(22);
66
67 return crypt($password, $salt);
68
69 case JCryptPassword::MD5:
70 $salt = $this->getSalt(12);
71
72 $salt = '$1$' . $salt;
73
74 return crypt($password, $salt);
75
76 case JCryptPassword::JOOMLA:
77 $salt = $this->getSalt(32);
78
79 return md5($password . $salt) . ':' . $salt;
80
81 default:
82 throw new InvalidArgumentException(sprintf('Hash type %s is not supported', $type));
83 break;
84 }
85 }
86
87 /**
88 * Sets the cost parameter for the generated hash for algorithms that use a cost factor.
89 *
90 * @param integer $cost The new cost value.
91 *
92 * @return void
93 *
94 * @since 12.2
95 * @deprecated 4.0 Use PHP 5.5's native password hashing API
96 */
97 public function setCost($cost)
98 {
99 $this->cost = $cost;
100 }
101
102 /**
103 * Generates a salt of specified length. The salt consists of characters in the set [./0-9A-Za-z].
104 *
105 * @param integer $length The number of characters to return.
106 *
107 * @return string The string of random characters.
108 *
109 * @since 12.2
110 * @deprecated 4.0 Use PHP 5.5's native password hashing API
111 */
112 protected function getSalt($length)
113 {
114 $bytes = ceil($length * 6 / 8);
115
116 $randomData = str_replace('+', '.', base64_encode(JCrypt::genRandomBytes($bytes)));
117
118 return substr($randomData, 0, $length);
119 }
120
121 /**
122 * Verifies a password hash
123 *
124 * @param string $password The password to verify.
125 * @param string $hash The password hash to check.
126 *
127 * @return boolean True if the password is valid, false otherwise.
128 *
129 * @since 12.2
130 * @deprecated 4.0 Use PHP 5.5's native password hashing API
131 */
132 public function verify($password, $hash)
133 {
134 // Check if the hash is a blowfish hash.
135 if (substr($hash, 0, 4) == '$2a$' || substr($hash, 0, 4) == '$2y$')
136 {
137 $type = '$2a$';
138
139 if (JCrypt::hasStrongPasswordSupport())
140 {
141 $type = '$2y$';
142 }
143
144 return password_verify($password, $hash);
145 }
146
147 // Check if the hash is an MD5 hash.
148 if (substr($hash, 0, 3) == '$1$')
149 {
150 return JCrypt::timingSafeCompare(crypt($password, $hash), $hash);
151 }
152
153 // Check if the hash is a Joomla hash.
154 if (preg_match('#[a-z0-9]{32}:[A-Za-z0-9]{32}#', $hash) === 1)
155 {
156 // Check the password
157 $parts = explode(':', $hash);
158 $salt = @$parts[1];
159
160 // Compile the hash to compare
161 // If the salt is empty AND there is a ':' in the original hash, we must append ':' at the end
162 $testcrypt = md5($password . $salt) . ($salt ? ':' . $salt : (strpos($hash, ':') !== false ? ':' : ''));
163
164 return JCrypt::timingSafeCompare($hash, $testcrypt);
165 }
166
167 return false;
168 }
169
170 /**
171 * Sets a default type
172 *
173 * @param string $type The value to set as default.
174 *
175 * @return void
176 *
177 * @since 12.3
178 * @deprecated 4.0 Use PHP 5.5's native password hashing API
179 */
180 public function setDefaultType($type)
181 {
182 if (!empty($type))
183 {
184 $this->defaultType = $type;
185 }
186 }
187
188 /**
189 * Gets the default type
190 *
191 * @return string $type The default type
192 *
193 * @since 12.3
194 * @deprecated 4.0 Use PHP 5.5's native password hashing API
195 */
196 public function getDefaultType()
197 {
198 return $this->defaultType;
199 }
200 }
201