reference/password/functions/password-hash.xml
c6b95280cf10b6b252683ee7d86416c4c27deb4e
...
...
@@ -1,4 +1,4 @@
1
-
<?xml version="1.0" encoding="utf-8"?>
1
+
<?xml version="1.0" encoding="utf-8"?>
2
2
<!-- $Revision$ -->
3
3

4
4
<refentry xml:id="function.password-hash" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
...
...
@@ -12,14 +12,12 @@
12
12
<methodsynopsis>
13
13
<type>string</type><methodname>password_hash</methodname>
14
14
<methodparam><type>string</type><parameter>password</parameter></methodparam>
15
-
<methodparam><type>integer</type><parameter>algo</parameter></methodparam>
16
-
<methodparam choice="opt"><type>array</type><parameter>options</parameter></methodparam>
15
+
<methodparam><type class="union"><type>string</type><type>int</type><type>null</type></type><parameter>algo</parameter></methodparam>
16
+
<methodparam choice="opt"><type>array</type><parameter>options</parameter><initializer>[]</initializer></methodparam>
17
17
</methodsynopsis>
18
18
<para>
19
19
<function>password_hash</function> creates a new password hash using a strong one-way hashing
20
-
algorithm. <function>password_hash</function> is compatible with <function>crypt</function>.
21
-
Therefore, password hashes created by <function>crypt</function> can be used with
22
-
<function>password_hash</function>.
20
+
algorithm.
23
21
</para>
24
22
<simpara>
25
23
The following algorithms are currently supported:
...
...
@@ -41,31 +39,83 @@
41
39
create the hash. This will produce a standard <function>crypt</function> compatible hash using
42
40
the "$2y$" identifier. The result will always be a 60 character string, &return.falseforfailure;.
43
41
</simpara>
42
+
</listitem>
43
+
<listitem>
44
+
<simpara>
45
+
<constant>PASSWORD_ARGON2I</constant> - Use the Argon2i hashing algorithm to create the hash.
46
+
This algorithm is only available if PHP has been compiled with Argon2 support.
47
+
</simpara>
48
+
</listitem>
49
+
<listitem>
50
+
<simpara>
51
+
<constant>PASSWORD_ARGON2ID</constant> - Use the Argon2id hashing algorithm to create the hash.
52
+
This algorithm is only available if PHP has been compiled with Argon2 support.
53
+
</simpara>
54
+
</listitem>
55
+
</itemizedlist>
56
+
</para>
57
+
<simpara>
58
+
Supported options for <constant>PASSWORD_BCRYPT</constant>:
59
+
</simpara>
60
+
<para>
61
+
<itemizedlist>
62
+
<listitem>
44
63
<para>
45
-
Supported Options:
64
+
<literal>salt</literal> (<type>string</type>) - to manually provide a salt to use when hashing the password.
65
+
Note that this will override and prevent a salt from being automatically generated.
66
+
</para>
67
+
<para>
68
+
If omitted, a random salt will be generated by <function>password_hash</function> for
69
+
each password hashed. This is the intended mode of operation.
70
+
</para>
71
+
<warning>
72
+
<para>
73
+
The salt option is deprecated. It is now
74
+
preferred to simply use the salt that is generated by default.
75
+
As of PHP 8.0.0, an explicitly given salt is ignored.
76
+
</para>
77
+
</warning>
78
+
</listitem>
79
+
<listitem>
80
+
<para>
81
+
<literal>cost</literal> (<type>int</type>) - which denotes the algorithmic cost that should be used.
82
+
Examples of these values can be found on the <function>crypt</function> page.
83
+
</para>
84
+
<para>
85
+
If omitted, a default value of <literal>10</literal> will be used. This is a good
86
+
baseline cost, but you may want to consider increasing it depending on your hardware.
46
87
</para>
47
-
<itemizedlist>
48
-
<listitem>
49
-
<para>
50
-
<literal>salt</literal> - to manually provide a salt to use when hashing the password.
51
-
Note that this will override and prevent a salt from being automatically generated.
52
-
</para>
53
-
<para>
54
-
If omitted, a random salt will be generated by <function>password_hash</function> for
55
-
each password hashed. This is the intended mode of operation.
56
-
</para>
57
-
</listitem>
58
-
<listitem>
59
-
<para>
60
-
<literal>cost</literal> - which denotes the algorithmic cost that should be used.
61
-
Examples of these values can be found on the <function>crypt</function> page.
62
-
</para>
63
-
<para>
64
-
If omitted, a default value of <literal>10</literal> will be used. This is a good
65
-
baseline cost, but you may want to consider increasing it depending on your hardware.
66
-
</para>
67
-
</listitem>
68
-
</itemizedlist>
88
+
</listitem>
89
+
</itemizedlist>
90
+
</para>
91
+
<simpara>
92
+
Supported options for <constant>PASSWORD_ARGON2I</constant>
93
+
and <constant>PASSWORD_ARGON2ID</constant>:
94
+
</simpara>
95
+
<para>
96
+
<itemizedlist>
97
+
<listitem>
98
+
<para>
99
+
<literal>memory_cost</literal> (<type>int</type>) - Maximum memory (in kibibytes) that may
100
+
be used to compute the Argon2 hash. Defaults to <constant>PASSWORD_ARGON2_DEFAULT_MEMORY_COST</constant>.
101
+
</para>
102
+
</listitem>
103
+
<listitem>
104
+
<para>
105
+
<literal>time_cost</literal> (<type>int</type>) - Maximum amount of time it may
106
+
take to compute the Argon2 hash. Defaults to <constant>PASSWORD_ARGON2_DEFAULT_TIME_COST</constant>.
107
+
</para>
108
+
</listitem>
109
+
<listitem>
110
+
<para>
111
+
<literal>threads</literal> (<type>int</type>) - Number of threads to use for computing
112
+
the Argon2 hash. Defaults to <constant>PASSWORD_ARGON2_DEFAULT_THREADS</constant>.
113
+
</para>
114
+
<warning>
115
+
<para>
116
+
Only available when PHP uses libargon2, not with libsodium implementation.
117
+
</para>
118
+
</warning>
69
119
</listitem>
70
120
</itemizedlist>
71
121
</para>
...
...
@@ -82,10 +132,10 @@
82
132
</para>
83
133
<caution>
84
134
<para>
85
-
Using the <constant>PASSWORD_BCRYPT</constant> for the
86
-
<parameter>algo</parameter> parameter, will result
135
+
Using the <constant>PASSWORD_BCRYPT</constant> as the
136
+
algorithm, will result
87
137
in the <parameter>password</parameter> parameter being truncated to a
88
-
maximum length of 72 characters.
138
+
maximum length of 72 bytes.
89
139
</para>
90
140
</caution>
91
141
</listitem>
...
...
@@ -116,7 +166,7 @@
116
166
<refsect1 role="returnvalues">
117
167
&reftitle.returnvalues;
118
168
<para>
119
-
Returns the hashed password, &return.falseforfailure;.
169
+
Returns the hashed password.
120
170
</para>
121
171
<para>
122
172
The used algorithm, cost and salt are returned as part of the hash. Therefore,
...
...
@@ -126,6 +176,64 @@
126
176
</para>
127
177
</refsect1>
128
178

179
+
<refsect1 role="changelog">
180
+
&reftitle.changelog;
181
+
<para>
182
+
<informaltable>
183
+
<tgroup cols="2">
184
+
<thead>
185
+
<row>
186
+
<entry>&Version;</entry>
187
+
<entry>&Description;</entry>
188
+
</row>
189
+
</thead>
190
+
<tbody>
191
+
<row>
192
+
<entry>8.0.0</entry>
193
+
<entry>
194
+
<function>password_hash</function> no longer returns &false; on failure, instead a
195
+
<classname>ValueError</classname> will be thrown if the password hashing algorithm
196
+
is not valid, or an <classname>Error</classname> if the password hashing failed
197
+
for an unknown error.
198
+
</entry>
199
+
</row>
200
+
<row>
201
+
<entry>8.0.0</entry>
202
+
<entry>
203
+
The <parameter>algo</parameter> parameter is nullable now.
204
+
</entry>
205
+
</row>
206
+
<row>
207
+
<entry>7.4.0</entry>
208
+
<entry>
209
+
The <parameter>algo</parameter> parameter expects a &string; now, but still accepts
210
+
&integer;s for backward compatibility.
211
+
</entry>
212
+
</row>
213
+
<row>
214
+
<entry>7.4.0</entry>
215
+
<entry>
216
+
The sodium extension provides an alternative implementation for Argon2 passwords.
217
+
</entry>
218
+
</row>
219
+
<row>
220
+
<entry>7.3.0</entry>
221
+
<entry>
222
+
Support for Argon2id passwords using <constant>PASSWORD_ARGON2ID</constant> was added.
223
+
</entry>
224
+
</row>
225
+
<row>
226
+
<entry>7.2.0</entry>
227
+
<entry>
228
+
Support for Argon2i passwords using <constant>PASSWORD_ARGON2I</constant> was added.
229
+
</entry>
230
+
</row>
231
+
</tbody>
232
+
</tgroup>
233
+
</informaltable>
234
+
</para>
235
+
</refsect1>
236
+

129
237
<refsect1 role="examples">
130
238
&reftitle.examples;
131
239
<para>
...
...
@@ -141,7 +249,7 @@
141
249
* Beware that DEFAULT may change over time, so you would want to prepare
142
250
* By allowing your storage to expand past 60 characters (255 would be good)
143
251
*/
144
-
echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT)."\n";
252
+
echo password_hash("rasmuslerdorf", PASSWORD_DEFAULT);
145
253
?>
146
254
]]>
147
255
</programlisting>
...
...
@@ -166,7 +274,7 @@ $2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a
166
274
$options = [
167
275
'cost' => 12,
168
276
];
169
-
echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options)."\n";
277
+
echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options);
170
278
?>
171
279
]]>
172
280
</programlisting>
...
...
@@ -178,65 +286,55 @@ $2y$12$QjSH496pcT5CEbzjD/vtVeH03tfHKFy36d4J0Ltp3lRtee9HDxY3K
178
286
</screen>
179
287
</example>
180
288
</para>
181
-
182
289
<para>
183
290
<example>
184
-
<title><function>password_hash</function> example setting salt manually</title>
291
+
<title><function>password_hash</function> example finding a good cost</title>
185
292
<programlisting role="php">
186
293
<![CDATA[
187
294
<?php
188
295
/**
189
-
* Note that the salt here is randomly generated.
190
-
* Never use a static salt or one that is not randomly generated.
191
-
*
192
-
* For the VAST majority of use-cases, let password_hash generate the salt randomly for you
296
+
* This code will benchmark your server to determine how high of a cost you can
297
+
* afford. You want to set the highest cost that you can without slowing down
298
+
* you server too much. 10 is a good baseline, and more is good if your servers
299
+
* are fast enough. The code below aims for ≤ 350 milliseconds stretching time,
300
+
* which is an appropriate delay for systems handling interactive logins.
193
301
*/
194
-
$options = [
195
-
'cost' => 11,
196
-
'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM),
197
-
];
198
-
echo password_hash("rasmuslerdorf", PASSWORD_BCRYPT, $options)."\n";
302
+
$timeTarget = 0.350; // 350 milliseconds
303
+

304
+
$cost = 10;
305
+
do {
306
+
$cost++;
307
+
$start = microtime(true);
308
+
password_hash("test", PASSWORD_BCRYPT, ["cost" => $cost]);
309
+
$end = microtime(true);
310
+
} while (($end - $start) < $timeTarget);
311
+

312
+
echo "Appropriate Cost Found: " . $cost;
199
313
?>
200
314
]]>
201
315
</programlisting>
202
316
&example.outputs.similar;
203
317
<screen>
204
318
<![CDATA[
205
-
$2y$11$q5MkhSBtlsJcNEVsYh64a.aCluzHnGog7TQAKVmQwO9C8xb.t89F.
319
+
Appropriate Cost Found: 12
206
320
]]>
207
321
</screen>
208
322
</example>
209
323
</para>
210
324
<para>
211
325
<example>
212
-
<title><function>password_hash</function> example finding a good cost</title>
326
+
<title><function>password_hash</function> example using Argon2i</title>
213
327
<programlisting role="php">
214
328
<![CDATA[
215
329
<?php
216
-
/**
217
-
* This code will benchmark your server to determine how high of a cost you can
218
-
* afford. You want to set the highest cost that you can without slowing down
219
-
* you server too much. 10 is a good baseline, and more is good if your servers
220
-
* are fast enough.
221
-
*/
222
-
$timeTarget = 0.2;
223
-

224
-
$cost = 9;
225
-
do {
226
-
$cost++;
227
-
$start = microtime(true);
228
-
password_hash("test", PASSWORD_BCRYPT, ["cost" => $cost]);
229
-
$end = microtime(true);
230
-
} while (($end - $start) < $timeTarget);
231
-

232
-
echo "Appropriate Cost Found: " . $cost . "\n";
330
+
echo 'Argon2i hash: ' . password_hash('rasmuslerdorf', PASSWORD_ARGON2I);
233
331
?>
234
332
]]>
235
333
</programlisting>
236
334
&example.outputs.similar;
237
335
<screen>
238
336
<![CDATA[
239
-
Appropriate Cost Found: 11
337
+
Argon2i hash: $argon2i$v=19$m=1024,t=2,p=2$YzJBSzV4TUhkMzc3d3laeg$zqU/1IN0/AogfP4cmSJI1vc8lpXRW9/S0sYY2i2jHT0
240
338
]]>
241
339
</screen>
242
340
</example>
...
...
@@ -247,15 +345,21 @@ Appropriate Cost Found: 11
247
345
&reftitle.notes;
248
346
<caution>
249
347
<para>
250
-
It is strongly recommended that you do not generate your own salt for this function.
251
-
It will create a secure salt automatically for you if you do not specify one.
348
+
It is strongly recommended that you do not generate your own salt for this
349
+
function. It will create a secure salt automatically for you if you do
350
+
not specify one.
351
+
</para>
352
+
<para>
353
+
As noted above, providing the <literal>salt</literal> option in PHP 7.0
354
+
will generate a deprecation warning. Support for providing a salt manually
355
+
has been removed in PHP 8.0.
252
356
</para>
253
357
</caution>
254
358
<note>
255
359
<para>
256
-
It is recommended that you test this function on your servers, and adjust the cost
257
-
parameter so that execution of the function takes approximately 0.1 to 0.5 seconds. The script
258
-
in the above example will help you choose a good cost value for your hardware.
360
+
It is recommended that you test this function on your servers, and adjust the cost parameter
361
+
so that execution of the function takes less than 350 milliseconds on interactive systems.
362
+
The script in the above example will help you choose a good cost value for your hardware.
259
363
</para>
260
364
</note>
261
365
<note>
...
...
@@ -266,16 +370,19 @@ Appropriate Cost Found: 11
266
370
<para>
267
371
<itemizedlist>
268
372
<listitem>
269
-
<simpara>Any new algorithm must be in core for at least 1 full release of PHP prior to becoming
270
-
default. So if, for example, a new algorithm is added in 5.5.5, it would not be eligible for
271
-
default until 5.7 (since 5.6 would be the first full release). But if a different algorithm was
272
-
added in 5.6.0, it would also be eligible for default at 5.7.0.
373
+
<simpara>
374
+
Any new algorithm must be in core for at least 1 full release of PHP
375
+
prior to becoming default. So if, for example, a new algorithm is added
376
+
in 7.5.5, it would not be eligible for default until 7.7 (since 7.6
377
+
would be the first full release). But if a different algorithm was added
378
+
in 7.6.0, it would also be eligible for default at 7.7.0.
273
379
</simpara>
274
380
</listitem>
275
381
<listitem>
276
382
<simpara>
277
-
The default should only change on a full release (5.6.0, 6.0.0, etc) and not on a revision release.
278
-
The only exception to this is in an emergency when a critical security flaw is found in the current
383
+
The default should only change in a full release (7.3.0, 8.0.0, etc)
384
+
and not in a revision release. The only exception to this is in an
385
+
emergency when a critical security flaw is found in the current
279
386
default.
280
387
</simpara>
281
388
</listitem>
...
...
@@ -289,8 +396,9 @@ Appropriate Cost Found: 11
289
396
<para>
290
397
<simplelist>
291
398
<member><function>password_verify</function></member>
399
+
<member><function>password_needs_rehash</function></member>
292
400
<member><function>crypt</function></member>
293
-
<member><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&url.password.compat;">userland implementation</link></member>
401
+
<member><function>sodium_crypto_pwhash_str</function></member>
294
402
</simplelist>
295
403
</para>
296
404
</refsect1>
297
405