1: <?php
2: /**
3: * PHP Password Library
4: *
5: * @package PHPassLib\Hashes
6: * @author Ryan Chouinard <rchouinard@gmail.com>
7: * @copyright Copyright (c) 2012, Ryan Chouinard
8: * @license MIT License - http://www.opensource.org/licenses/mit-license.php
9: * @version 3.0.0-dev
10: */
11:
12: namespace PHPassLib\Hash;
13:
14: use PHPassLib\Hash;
15: use PHPassLib\Utilities;
16: use PHPassLib\Exception\InvalidArgumentException;
17:
18: /**
19: * DES Crypt Module
20: *
21: * The DES Crypt algorithm is the original DES-based Unix crypt algorithm. It
22: * is an old algorithm which should be avoided for new applications.
23: *
24: * Supported parameters:
25: *
26: * <ul>
27: * <li><b>salt:</b> Optional salt string. If provided, it must be a 2
28: * character string containing only characters in the regex range
29: * [./0-9A-Za-z]. It is highly recommended that this parameter be left blank,
30: * in which case the library will generate a suitable salt for you.</li>
31: * </ul>
32: *
33: * This module uses PHP's native crypt() function, which has had native support
34: * for DES Crypt since 5.3.0.
35: *
36: * @package PHPassLib\Hashes
37: * @author Ryan Chouinard <rchouinard@gmail.com>
38: * @copyright Copyright (c) 2012, Ryan Chouinard
39: * @license MIT License - http://www.opensource.org/licenses/mit-license.php
40: */
41: class DESCrypt implements Hash
42: {
43:
44: /**
45: * Generate a config string from an array.
46: *
47: * @param array $config Array of configuration options.
48: * @return string Configuration string.
49: * @throws InvalidArgumentException Throws an InvalidArgumentException if
50: * any passed-in configuration options are invalid.
51: */
52: public static function genConfig(array $config = array ())
53: {
54: $defaults = array (
55: 'salt' => Utilities::encode64(Utilities::genRandomBytes(1)),
56: );
57: $config = array_merge($defaults, array_change_key_case($config, CASE_LOWER));
58:
59: $string = '*1';
60: if (self::validateOptions($config)) {
61: $string = $config['salt'];
62: }
63:
64: return $string;
65: }
66:
67: /**
68: * Parse a config string into an array.
69: *
70: * @param string $config Configuration string.
71: * @return array Array of configuration options or false on failure.
72: */
73: public static function parseConfig($config)
74: {
75: $options = false;
76: $matches = array ();
77: if (preg_match('/^([\.\/0-9A-Za-z]{2})/', $config, $matches)) {
78: $options = array (
79: 'salt' => $matches[1],
80: );
81:
82: try {
83: self::validateOptions($options);
84: } catch (InvalidArgumentException $e) {
85: $options = false;
86: }
87: }
88:
89: return $options;
90: }
91:
92: /**
93: * Generate a password hash using a config string.
94: *
95: * @param string $password Password string.
96: * @param string $config Configuration string.
97: * @return string Returns the hash string on success. On failure, one of
98: * *0 or *1 is returned.
99: */
100: public static function genHash($password, $config)
101: {
102: $hash = crypt($password, $config);
103: if (!preg_match('/^[\.\/0-9A-Za-z]{13}$/', $hash)) {
104: $hash = ($config == '*0') ? '*1' : '*0';
105: }
106:
107: return $hash;
108: }
109:
110: /**
111: * Generate a password hash using a config string or array.
112: *
113: * @param string $password Password string.
114: * @param string|array $config Optional config string or array of options.
115: * @return string Returns the hash string on success. On failure, one of
116: * *0 or *1 is returned.
117: * @throws InvalidArgumentException Throws an InvalidArgumentException if
118: * any passed-in configuration options are invalid.
119: *
120: */
121: public static function hash($password, $config = array ())
122: {
123: if (is_array($config)) {
124: $config = self::genConfig($config);
125: }
126:
127: return self::genHash($password, $config);
128: }
129:
130: /**
131: * Verify a password against a hash string.
132: *
133: * @param string $password Password string.
134: * @param string $hash Hash string.
135: * @return boolean Returns true if the password matches, false otherwise.
136: */
137: public static function verify($password, $hash)
138: {
139: return ($hash === self::hash($password, $hash));
140: }
141:
142: /**
143: * @param array $options
144: * @return boolean
145: * @throws InvalidArgumentException
146: */
147: protected static function validateOptions(array $options)
148: {
149: $options = array_change_key_case($options, CASE_LOWER);
150: foreach ($options as $option => $value) switch ($option) {
151:
152: case 'salt':
153: if (!preg_match('/^[\.\/0-9A-Za-z]{2}$/', $value)) {
154: throw new InvalidArgumentException('Invalid salt parameter');
155: }
156: break;
157:
158: default:
159: break;
160:
161: }
162:
163: return true;
164: }
165:
166: }
167: