Passed
Push — master ( 1ae1d9...d63fc8 )
by Roeland
12:34 queued 12s
created
lib/private/Security/Hasher.php 2 patches
Indentation   +168 added lines, -168 removed lines patch added patch discarded remove patch
@@ -50,173 +50,173 @@
 block discarded – undo
50 50
  * @package OC\Security
51 51
  */
52 52
 class Hasher implements IHasher {
53
-	/** @var IConfig */
54
-	private $config;
55
-	/** @var array Options passed to password_hash and password_needs_rehash */
56
-	private $options = [];
57
-	/** @var string Salt used for legacy passwords */
58
-	private $legacySalt = null;
59
-
60
-	/**
61
-	 * @param IConfig $config
62
-	 */
63
-	public function __construct(IConfig $config) {
64
-		$this->config = $config;
65
-
66
-		if (\defined('PASSWORD_ARGON2I')) {
67
-			// password_hash fails, when the minimum values are undershot.
68
-			// In this case, ignore and revert to default
69
-			if ($this->config->getSystemValueInt('hashingMemoryCost', PASSWORD_ARGON2_DEFAULT_MEMORY_COST) >= 8) {
70
-				$this->options['memory_cost'] = $this->config->getSystemValueInt('hashingMemoryCost', PASSWORD_ARGON2_DEFAULT_MEMORY_COST);
71
-			}
72
-			if ($this->config->getSystemValueInt('hashingTimeCost', PASSWORD_ARGON2_DEFAULT_MEMORY_COST) >= 1) {
73
-				$this->options['time_cost'] = $this->config->getSystemValueInt('hashingTimeCost', PASSWORD_ARGON2_DEFAULT_TIME_COST);
74
-			}
75
-			if ($this->config->getSystemValueInt('hashingThreads', PASSWORD_ARGON2_DEFAULT_MEMORY_COST) >= 1) {
76
-				$this->options['threads'] = $this->config->getSystemValueInt('hashingThreads', PASSWORD_ARGON2_DEFAULT_THREADS);
77
-			}
78
-		}
79
-
80
-		$hashingCost = $this->config->getSystemValue('hashingCost', null);
81
-		if(!\is_null($hashingCost)) {
82
-			$this->options['cost'] = $hashingCost;
83
-		}
84
-	}
85
-
86
-	/**
87
-	 * Hashes a message using PHP's `password_hash` functionality.
88
-	 * Please note that the size of the returned string is not guaranteed
89
-	 * and can be up to 255 characters.
90
-	 *
91
-	 * @param string $message Message to generate hash from
92
-	 * @return string Hash of the message with appended version parameter
93
-	 */
94
-	public function hash(string $message): string {
95
-		$alg = $this->getPrefferedAlgorithm();
96
-
97
-		if (\defined('PASSWORD_ARGON2I') && $alg === PASSWORD_ARGON2I) {
98
-			return 2 . '|' . password_hash($message, PASSWORD_ARGON2I, $this->options);
99
-		}
100
-
101
-		return 1 . '|' . password_hash($message, PASSWORD_BCRYPT, $this->options);
102
-	}
103
-
104
-	/**
105
-	 * Get the version and hash from a prefixedHash
106
-	 * @param string $prefixedHash
107
-	 * @return null|array Null if the hash is not prefixed, otherwise array('version' => 1, 'hash' => 'foo')
108
-	 */
109
-	protected function splitHash(string $prefixedHash) {
110
-		$explodedString = explode('|', $prefixedHash, 2);
111
-		if(\count($explodedString) === 2) {
112
-			if((int)$explodedString[0] > 0) {
113
-				return ['version' => (int)$explodedString[0], 'hash' => $explodedString[1]];
114
-			}
115
-		}
116
-
117
-		return null;
118
-	}
119
-
120
-	/**
121
-	 * Verify legacy hashes
122
-	 * @param string $message Message to verify
123
-	 * @param string $hash Assumed hash of the message
124
-	 * @param null|string &$newHash Reference will contain the updated hash
125
-	 * @return bool Whether $hash is a valid hash of $message
126
-	 */
127
-	protected function legacyHashVerify($message, $hash, &$newHash = null): bool {
128
-		if(empty($this->legacySalt)) {
129
-			$this->legacySalt = $this->config->getSystemValue('passwordsalt', '');
130
-		}
131
-
132
-		// Verify whether it matches a legacy PHPass or SHA1 string
133
-		$hashLength = \strlen($hash);
134
-		if(($hashLength === 60 && password_verify($message.$this->legacySalt, $hash)) ||
135
-			($hashLength === 40 && hash_equals($hash, sha1($message)))) {
136
-			$newHash = $this->hash($message);
137
-			return true;
138
-		}
139
-
140
-		return false;
141
-	}
142
-
143
-	/**
144
-	 * Verify V1 (blowfish) hashes
145
-	 * @param string $message Message to verify
146
-	 * @param string $hash Assumed hash of the message
147
-	 * @param null|string &$newHash Reference will contain the updated hash if necessary. Update the existing hash with this one.
148
-	 * @return bool Whether $hash is a valid hash of $message
149
-	 */
150
-	protected function verifyHashV1(string $message, string $hash, &$newHash = null): bool {
151
-		if(password_verify($message, $hash)) {
152
-			if ($this->needsRehash($hash)) {
153
-				$newHash = $this->hash($message);
154
-			}
155
-			return true;
156
-		}
157
-
158
-		return false;
159
-	}
160
-
161
-	/**
162
-	 * Verify V2 (argon2i) hashes
163
-	 * @param string $message Message to verify
164
-	 * @param string $hash Assumed hash of the message
165
-	 * @param null|string &$newHash Reference will contain the updated hash if necessary. Update the existing hash with this one.
166
-	 * @return bool Whether $hash is a valid hash of $message
167
-	 */
168
-	protected function verifyHashV2(string $message, string $hash, &$newHash = null) : bool {
169
-		if(password_verify($message, $hash)) {
170
-			if($this->needsRehash($hash)) {
171
-				$newHash = $this->hash($message);
172
-			}
173
-			return true;
174
-		}
175
-
176
-		return false;
177
-	}
178
-
179
-	/**
180
-	 * @param string $message Message to verify
181
-	 * @param string $hash Assumed hash of the message
182
-	 * @param null|string &$newHash Reference will contain the updated hash if necessary. Update the existing hash with this one.
183
-	 * @return bool Whether $hash is a valid hash of $message
184
-	 */
185
-	public function verify(string $message, string $hash, &$newHash = null): bool {
186
-		$splittedHash = $this->splitHash($hash);
187
-
188
-		if(isset($splittedHash['version'])) {
189
-			switch ($splittedHash['version']) {
190
-				case 2:
191
-					return $this->verifyHashV2($message, $splittedHash['hash'], $newHash);
192
-				case 1:
193
-					return $this->verifyHashV1($message, $splittedHash['hash'], $newHash);
194
-			}
195
-		} else {
196
-			return $this->legacyHashVerify($message, $hash, $newHash);
197
-		}
198
-
199
-		return false;
200
-	}
201
-
202
-	private function needsRehash(string $hash): bool {
203
-		$algorithm = $this->getPrefferedAlgorithm();
204
-
205
-		return password_needs_rehash($hash, $algorithm, $this->options);
206
-	}
207
-
208
-	private function getPrefferedAlgorithm() {
209
-		$default = PASSWORD_BCRYPT;
210
-		if (\defined('PASSWORD_ARGON2I')) {
211
-			$default = PASSWORD_ARGON2I;
212
-		}
213
-
214
-		// Check if we should use PASSWORD_DEFAULT
215
-		if ($this->config->getSystemValue('hashing_default_password', false) === true) {
216
-			$default = PASSWORD_DEFAULT;
217
-		}
218
-
219
-		return $default;
220
-	}
53
+    /** @var IConfig */
54
+    private $config;
55
+    /** @var array Options passed to password_hash and password_needs_rehash */
56
+    private $options = [];
57
+    /** @var string Salt used for legacy passwords */
58
+    private $legacySalt = null;
59
+
60
+    /**
61
+     * @param IConfig $config
62
+     */
63
+    public function __construct(IConfig $config) {
64
+        $this->config = $config;
65
+
66
+        if (\defined('PASSWORD_ARGON2I')) {
67
+            // password_hash fails, when the minimum values are undershot.
68
+            // In this case, ignore and revert to default
69
+            if ($this->config->getSystemValueInt('hashingMemoryCost', PASSWORD_ARGON2_DEFAULT_MEMORY_COST) >= 8) {
70
+                $this->options['memory_cost'] = $this->config->getSystemValueInt('hashingMemoryCost', PASSWORD_ARGON2_DEFAULT_MEMORY_COST);
71
+            }
72
+            if ($this->config->getSystemValueInt('hashingTimeCost', PASSWORD_ARGON2_DEFAULT_MEMORY_COST) >= 1) {
73
+                $this->options['time_cost'] = $this->config->getSystemValueInt('hashingTimeCost', PASSWORD_ARGON2_DEFAULT_TIME_COST);
74
+            }
75
+            if ($this->config->getSystemValueInt('hashingThreads', PASSWORD_ARGON2_DEFAULT_MEMORY_COST) >= 1) {
76
+                $this->options['threads'] = $this->config->getSystemValueInt('hashingThreads', PASSWORD_ARGON2_DEFAULT_THREADS);
77
+            }
78
+        }
79
+
80
+        $hashingCost = $this->config->getSystemValue('hashingCost', null);
81
+        if(!\is_null($hashingCost)) {
82
+            $this->options['cost'] = $hashingCost;
83
+        }
84
+    }
85
+
86
+    /**
87
+     * Hashes a message using PHP's `password_hash` functionality.
88
+     * Please note that the size of the returned string is not guaranteed
89
+     * and can be up to 255 characters.
90
+     *
91
+     * @param string $message Message to generate hash from
92
+     * @return string Hash of the message with appended version parameter
93
+     */
94
+    public function hash(string $message): string {
95
+        $alg = $this->getPrefferedAlgorithm();
96
+
97
+        if (\defined('PASSWORD_ARGON2I') && $alg === PASSWORD_ARGON2I) {
98
+            return 2 . '|' . password_hash($message, PASSWORD_ARGON2I, $this->options);
99
+        }
100
+
101
+        return 1 . '|' . password_hash($message, PASSWORD_BCRYPT, $this->options);
102
+    }
103
+
104
+    /**
105
+     * Get the version and hash from a prefixedHash
106
+     * @param string $prefixedHash
107
+     * @return null|array Null if the hash is not prefixed, otherwise array('version' => 1, 'hash' => 'foo')
108
+     */
109
+    protected function splitHash(string $prefixedHash) {
110
+        $explodedString = explode('|', $prefixedHash, 2);
111
+        if(\count($explodedString) === 2) {
112
+            if((int)$explodedString[0] > 0) {
113
+                return ['version' => (int)$explodedString[0], 'hash' => $explodedString[1]];
114
+            }
115
+        }
116
+
117
+        return null;
118
+    }
119
+
120
+    /**
121
+     * Verify legacy hashes
122
+     * @param string $message Message to verify
123
+     * @param string $hash Assumed hash of the message
124
+     * @param null|string &$newHash Reference will contain the updated hash
125
+     * @return bool Whether $hash is a valid hash of $message
126
+     */
127
+    protected function legacyHashVerify($message, $hash, &$newHash = null): bool {
128
+        if(empty($this->legacySalt)) {
129
+            $this->legacySalt = $this->config->getSystemValue('passwordsalt', '');
130
+        }
131
+
132
+        // Verify whether it matches a legacy PHPass or SHA1 string
133
+        $hashLength = \strlen($hash);
134
+        if(($hashLength === 60 && password_verify($message.$this->legacySalt, $hash)) ||
135
+            ($hashLength === 40 && hash_equals($hash, sha1($message)))) {
136
+            $newHash = $this->hash($message);
137
+            return true;
138
+        }
139
+
140
+        return false;
141
+    }
142
+
143
+    /**
144
+     * Verify V1 (blowfish) hashes
145
+     * @param string $message Message to verify
146
+     * @param string $hash Assumed hash of the message
147
+     * @param null|string &$newHash Reference will contain the updated hash if necessary. Update the existing hash with this one.
148
+     * @return bool Whether $hash is a valid hash of $message
149
+     */
150
+    protected function verifyHashV1(string $message, string $hash, &$newHash = null): bool {
151
+        if(password_verify($message, $hash)) {
152
+            if ($this->needsRehash($hash)) {
153
+                $newHash = $this->hash($message);
154
+            }
155
+            return true;
156
+        }
157
+
158
+        return false;
159
+    }
160
+
161
+    /**
162
+     * Verify V2 (argon2i) hashes
163
+     * @param string $message Message to verify
164
+     * @param string $hash Assumed hash of the message
165
+     * @param null|string &$newHash Reference will contain the updated hash if necessary. Update the existing hash with this one.
166
+     * @return bool Whether $hash is a valid hash of $message
167
+     */
168
+    protected function verifyHashV2(string $message, string $hash, &$newHash = null) : bool {
169
+        if(password_verify($message, $hash)) {
170
+            if($this->needsRehash($hash)) {
171
+                $newHash = $this->hash($message);
172
+            }
173
+            return true;
174
+        }
175
+
176
+        return false;
177
+    }
178
+
179
+    /**
180
+     * @param string $message Message to verify
181
+     * @param string $hash Assumed hash of the message
182
+     * @param null|string &$newHash Reference will contain the updated hash if necessary. Update the existing hash with this one.
183
+     * @return bool Whether $hash is a valid hash of $message
184
+     */
185
+    public function verify(string $message, string $hash, &$newHash = null): bool {
186
+        $splittedHash = $this->splitHash($hash);
187
+
188
+        if(isset($splittedHash['version'])) {
189
+            switch ($splittedHash['version']) {
190
+                case 2:
191
+                    return $this->verifyHashV2($message, $splittedHash['hash'], $newHash);
192
+                case 1:
193
+                    return $this->verifyHashV1($message, $splittedHash['hash'], $newHash);
194
+            }
195
+        } else {
196
+            return $this->legacyHashVerify($message, $hash, $newHash);
197
+        }
198
+
199
+        return false;
200
+    }
201
+
202
+    private function needsRehash(string $hash): bool {
203
+        $algorithm = $this->getPrefferedAlgorithm();
204
+
205
+        return password_needs_rehash($hash, $algorithm, $this->options);
206
+    }
207
+
208
+    private function getPrefferedAlgorithm() {
209
+        $default = PASSWORD_BCRYPT;
210
+        if (\defined('PASSWORD_ARGON2I')) {
211
+            $default = PASSWORD_ARGON2I;
212
+        }
213
+
214
+        // Check if we should use PASSWORD_DEFAULT
215
+        if ($this->config->getSystemValue('hashing_default_password', false) === true) {
216
+            $default = PASSWORD_DEFAULT;
217
+        }
218
+
219
+        return $default;
220
+    }
221 221
 
222 222
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -78,7 +78,7 @@  discard block
 block discarded – undo
78 78
 		}
79 79
 
80 80
 		$hashingCost = $this->config->getSystemValue('hashingCost', null);
81
-		if(!\is_null($hashingCost)) {
81
+		if (!\is_null($hashingCost)) {
82 82
 			$this->options['cost'] = $hashingCost;
83 83
 		}
84 84
 	}
@@ -95,10 +95,10 @@  discard block
 block discarded – undo
95 95
 		$alg = $this->getPrefferedAlgorithm();
96 96
 
97 97
 		if (\defined('PASSWORD_ARGON2I') && $alg === PASSWORD_ARGON2I) {
98
-			return 2 . '|' . password_hash($message, PASSWORD_ARGON2I, $this->options);
98
+			return 2.'|'.password_hash($message, PASSWORD_ARGON2I, $this->options);
99 99
 		}
100 100
 
101
-		return 1 . '|' . password_hash($message, PASSWORD_BCRYPT, $this->options);
101
+		return 1.'|'.password_hash($message, PASSWORD_BCRYPT, $this->options);
102 102
 	}
103 103
 
104 104
 	/**
@@ -108,9 +108,9 @@  discard block
 block discarded – undo
108 108
 	 */
109 109
 	protected function splitHash(string $prefixedHash) {
110 110
 		$explodedString = explode('|', $prefixedHash, 2);
111
-		if(\count($explodedString) === 2) {
112
-			if((int)$explodedString[0] > 0) {
113
-				return ['version' => (int)$explodedString[0], 'hash' => $explodedString[1]];
111
+		if (\count($explodedString) === 2) {
112
+			if ((int) $explodedString[0] > 0) {
113
+				return ['version' => (int) $explodedString[0], 'hash' => $explodedString[1]];
114 114
 			}
115 115
 		}
116 116
 
@@ -125,13 +125,13 @@  discard block
 block discarded – undo
125 125
 	 * @return bool Whether $hash is a valid hash of $message
126 126
 	 */
127 127
 	protected function legacyHashVerify($message, $hash, &$newHash = null): bool {
128
-		if(empty($this->legacySalt)) {
128
+		if (empty($this->legacySalt)) {
129 129
 			$this->legacySalt = $this->config->getSystemValue('passwordsalt', '');
130 130
 		}
131 131
 
132 132
 		// Verify whether it matches a legacy PHPass or SHA1 string
133 133
 		$hashLength = \strlen($hash);
134
-		if(($hashLength === 60 && password_verify($message.$this->legacySalt, $hash)) ||
134
+		if (($hashLength === 60 && password_verify($message.$this->legacySalt, $hash)) ||
135 135
 			($hashLength === 40 && hash_equals($hash, sha1($message)))) {
136 136
 			$newHash = $this->hash($message);
137 137
 			return true;
@@ -148,7 +148,7 @@  discard block
 block discarded – undo
148 148
 	 * @return bool Whether $hash is a valid hash of $message
149 149
 	 */
150 150
 	protected function verifyHashV1(string $message, string $hash, &$newHash = null): bool {
151
-		if(password_verify($message, $hash)) {
151
+		if (password_verify($message, $hash)) {
152 152
 			if ($this->needsRehash($hash)) {
153 153
 				$newHash = $this->hash($message);
154 154
 			}
@@ -166,8 +166,8 @@  discard block
 block discarded – undo
166 166
 	 * @return bool Whether $hash is a valid hash of $message
167 167
 	 */
168 168
 	protected function verifyHashV2(string $message, string $hash, &$newHash = null) : bool {
169
-		if(password_verify($message, $hash)) {
170
-			if($this->needsRehash($hash)) {
169
+		if (password_verify($message, $hash)) {
170
+			if ($this->needsRehash($hash)) {
171 171
 				$newHash = $this->hash($message);
172 172
 			}
173 173
 			return true;
@@ -185,7 +185,7 @@  discard block
 block discarded – undo
185 185
 	public function verify(string $message, string $hash, &$newHash = null): bool {
186 186
 		$splittedHash = $this->splitHash($hash);
187 187
 
188
-		if(isset($splittedHash['version'])) {
188
+		if (isset($splittedHash['version'])) {
189 189
 			switch ($splittedHash['version']) {
190 190
 				case 2:
191 191
 					return $this->verifyHashV2($message, $splittedHash['hash'], $newHash);
Please login to merge, or discard this patch.