mirror of
https://github.com/php/doc-en.git
synced 2026-03-23 23:32:18 +01:00
Tweak the title and depersonalize the password hashing FAQ section (#3796)
Also streamlines the mentions of `crypt()` and discourages its use
This commit is contained in:
@@ -1,164 +1,159 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- $Revision$ -->
|
||||
<chapter xml:id="faq.passwords" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Safe Password Hashing</title>
|
||||
<title>Hashing passwords safely and securely</title>
|
||||
<titleabbrev>Password Hashing</titleabbrev>
|
||||
|
||||
<para>
|
||||
<simpara>
|
||||
This section explains the reasons behind using hashing functions
|
||||
to secure passwords, as well as how to do so effectively.
|
||||
</para>
|
||||
</simpara>
|
||||
|
||||
<qandaset>
|
||||
<qandaentry xml:id="faq.passwords.hashing">
|
||||
<question>
|
||||
<para>
|
||||
Why should I hash passwords supplied by users of my application?
|
||||
</para>
|
||||
<simpara>
|
||||
Why should passwords supplied by users be hashed?
|
||||
</simpara>
|
||||
</question>
|
||||
<answer>
|
||||
<para>
|
||||
<simpara>
|
||||
Password hashing is one of the most basic security considerations that
|
||||
must be made when designing any application that accepts passwords
|
||||
from users. Without hashing, any passwords that are stored in your
|
||||
application's database can be stolen if the database is compromised, and
|
||||
then immediately used to compromise not only your application, but also
|
||||
the accounts of your users on other services, if they do not use
|
||||
must be made when designing any application or service that accepts passwords
|
||||
from users. Without hashing, any passwords that are stored
|
||||
can be stolen if the data store is compromised, and
|
||||
then immediately used to compromise not only the application or service, but also
|
||||
the accounts of users on other services, if they do not use
|
||||
unique passwords.
|
||||
</para>
|
||||
<para>
|
||||
By applying a hashing algorithm to your user's passwords before storing
|
||||
them in your database, you make it implausible for any attacker to
|
||||
</simpara>
|
||||
<simpara>
|
||||
By applying a hashing algorithm to the user's passwords before storing
|
||||
them, it becomes implausible for any attacker to
|
||||
determine the original password, while still being able to compare
|
||||
the resulting hash to the original password in the future.
|
||||
</para>
|
||||
<para>
|
||||
</simpara>
|
||||
<simpara>
|
||||
It is important to note, however, that hashing passwords only protects
|
||||
them from being compromised in your data store, but does not necessarily
|
||||
protect them from being intercepted by malicious code injected into your
|
||||
application itself.
|
||||
</para>
|
||||
them from being compromised in the data store, but does not necessarily
|
||||
protect them from being intercepted by malicious code injected into the
|
||||
application or service itself.
|
||||
</simpara>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry xml:id="faq.passwords.fasthash">
|
||||
<question>
|
||||
<para>
|
||||
<simpara>
|
||||
Why are common hashing functions such as <function>md5</function> and
|
||||
<function>sha1</function> unsuitable for passwords?
|
||||
</para>
|
||||
</simpara>
|
||||
</question>
|
||||
<answer>
|
||||
<para>
|
||||
<simpara>
|
||||
Hashing algorithms such as MD5, SHA1 and SHA256 are designed to be
|
||||
very fast and efficient. With modern techniques and computer equipment,
|
||||
it has become trivial to "brute force" the output of these algorithms,
|
||||
it has become trivial to <quote>brute force</quote> the output of these algorithms,
|
||||
in order to determine the original input.
|
||||
</para>
|
||||
<para>
|
||||
Because of how quickly a modern computer can "reverse" these hashing
|
||||
</simpara>
|
||||
<simpara>
|
||||
Because of how quickly a modern computer can <quote>reverse</quote> these hashing
|
||||
algorithms, many security professionals strongly suggest against
|
||||
their use for password hashing.
|
||||
</para>
|
||||
</simpara>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry xml:id="faq.passwords.bestpractice">
|
||||
<question>
|
||||
<para>
|
||||
How should I hash my passwords, if the common hash functions are
|
||||
<simpara>
|
||||
How should passwords be hashed, if the common hash functions are
|
||||
not suitable?
|
||||
</para>
|
||||
</simpara>
|
||||
</question>
|
||||
<answer>
|
||||
<para>
|
||||
<simpara>
|
||||
When hashing passwords, the two most important considerations are the
|
||||
computational expense, and the salt. The more computationally expensive
|
||||
the hashing algorithm, the longer it will take to brute force its
|
||||
output.
|
||||
</para>
|
||||
<para>
|
||||
</simpara>
|
||||
<simpara>
|
||||
PHP provides
|
||||
<link linkend="book.password">a native password hashing API</link> that
|
||||
safely handles both <link linkend="function.password-hash">hashing</link>
|
||||
and <link linkend="function.password-verify">verifying passwords</link>
|
||||
in a secure manner.
|
||||
</para>
|
||||
<!-- TODO Drop mention of crypt? -->
|
||||
<para>
|
||||
Another option is the <function>crypt</function> function, which
|
||||
supports several hashing algorithms. When using
|
||||
this function, you are guaranteed that the algorithm you select is
|
||||
available, as PHP contains native implementations of each supported
|
||||
algorithm, in case one or more are not supported by your system.
|
||||
</para>
|
||||
<para>
|
||||
</simpara>
|
||||
<simpara>
|
||||
The suggested algorithm to use when hashing passwords is Blowfish, which
|
||||
is also the default used by the password hashing API, as it is
|
||||
significantly more computationally expensive than MD5 or SHA1, while
|
||||
still being scalable.
|
||||
</para>
|
||||
<para>
|
||||
Note that if you are using <function>crypt</function> to verify a
|
||||
password, you will need to take care to prevent timing attacks by using
|
||||
a constant time string comparison. Neither PHP's
|
||||
<link linkend="language.operators.comparison">== and === operators</link>
|
||||
nor <function>strcmp</function> perform constant time string
|
||||
comparisons. As <function>password_verify</function> will do this for
|
||||
you, you are strongly encouraged to use the
|
||||
</simpara>
|
||||
<simpara>
|
||||
The <function>crypt</function> function is also available for password
|
||||
hashing, but it is only recommended for interoperability with other
|
||||
systems.
|
||||
Instead, it is strongly encouraged to use the
|
||||
<link linkend="book.password">native password hashing API</link>
|
||||
whenever possible.
|
||||
</para>
|
||||
</simpara>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry xml:id="faq.passwords.salt">
|
||||
<question>
|
||||
<para>
|
||||
<simpara>
|
||||
What is a salt?
|
||||
</para>
|
||||
</simpara>
|
||||
</question>
|
||||
<answer>
|
||||
<para>
|
||||
<simpara>
|
||||
A cryptographic salt is data which is applied during the hashing process
|
||||
in order to eliminate the possibility of the output being looked up
|
||||
in a list of pre-calculated pairs of hashes and their input, known as
|
||||
a rainbow table.
|
||||
</para>
|
||||
<para>
|
||||
</simpara>
|
||||
<simpara>
|
||||
In more simple terms, a salt is a bit of additional data which makes
|
||||
your hashes significantly more difficult to crack. There are a number of
|
||||
hashes significantly more difficult to crack. There are a number of
|
||||
services online which provide extensive lists of pre-computed hashes, as
|
||||
well as the original input for those hashes. The use of a salt makes it
|
||||
implausible or impossible to find the resulting hash in one of these
|
||||
lists.
|
||||
</para>
|
||||
<para>
|
||||
</simpara>
|
||||
<simpara>
|
||||
<function>password_hash</function> will create a random salt if one
|
||||
isn't provided, and this is generally the easiest and most secure
|
||||
approach.
|
||||
</para>
|
||||
</simpara>
|
||||
</answer>
|
||||
</qandaentry>
|
||||
<qandaentry xml:id="faq.password.storing-salts">
|
||||
<question>
|
||||
<para>
|
||||
How do I store my salts?
|
||||
</para>
|
||||
<simpara>
|
||||
How are salts stored?
|
||||
</simpara>
|
||||
</question>
|
||||
<answer>
|
||||
<para>
|
||||
<simpara>
|
||||
When using <function>password_hash</function> or
|
||||
<function>crypt</function>, the return value includes the salt as part
|
||||
of the generated hash. This value should be stored verbatim in your
|
||||
of the generated hash. This value should be stored verbatim in the
|
||||
database, as it includes information about the hash function that was
|
||||
used and can then be given directly to
|
||||
<function>password_verify</function> or <function>crypt</function> when
|
||||
verifying passwords.
|
||||
</para>
|
||||
<para>
|
||||
<function>password_verify</function> when verifying passwords.
|
||||
</simpara>
|
||||
<warning>
|
||||
<simpara>
|
||||
<function>password_verify</function> should always be used instead
|
||||
of re-hashing and comparing the result to a stored hash in order
|
||||
to avoid timing attacks.
|
||||
</simpara>
|
||||
</warning>
|
||||
<simpara>
|
||||
The following diagram shows the format of a return value from
|
||||
<function>crypt</function> or <function>password_hash</function>. As you
|
||||
can see, they are self-contained, with all the information on the
|
||||
<function>crypt</function> or <function>password_hash</function>. As can
|
||||
be seen, they are self-contained, with all the information on the
|
||||
algorithm and salt required for future password verification.
|
||||
</para>
|
||||
</simpara>
|
||||
<para>
|
||||
<mediaobject>
|
||||
<alt>
|
||||
|
||||
Reference in New Issue
Block a user