mirror of
https://github.com/sigmasternchen/php-doc-en
synced 2025-03-15 08:28:54 +00:00
199 lines
7.4 KiB
XML
199 lines
7.4 KiB
XML
<?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>
|
|
<titleabbrev>Password Hashing</titleabbrev>
|
|
|
|
<para>
|
|
This section explains the reasons behind using hashing functions
|
|
to secure passwords, as well as how to do so effectively.
|
|
</para>
|
|
|
|
<qandaset>
|
|
<qandaentry xml:id="faq.passwords.hashing">
|
|
<question>
|
|
<para>
|
|
Why should I hash passwords supplied by users of my application?
|
|
</para>
|
|
</question>
|
|
<answer>
|
|
<para>
|
|
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
|
|
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
|
|
determine the original password, while still being able to compare
|
|
the resulting hash to the original password in the future.
|
|
</para>
|
|
<para>
|
|
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>
|
|
</answer>
|
|
</qandaentry>
|
|
<qandaentry xml:id="faq.passwords.fasthash">
|
|
<question>
|
|
<para>
|
|
Why are common hashing functions such as <function>md5</function> and
|
|
<function>sha1</function> unsuitable for passwords?
|
|
</para>
|
|
</question>
|
|
<answer>
|
|
<para>
|
|
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,
|
|
in order to determine the original input.
|
|
</para>
|
|
<para>
|
|
Because of how quickly a modern computer can "reverse" these hashing
|
|
algorithms, many security professionals strongly suggest against
|
|
their use for password hashing.
|
|
</para>
|
|
</answer>
|
|
</qandaentry>
|
|
<qandaentry xml:id="faq.passwords.bestpractice">
|
|
<question>
|
|
<para>
|
|
How should I hash my passwords, if the common hash functions are
|
|
not suitable?
|
|
</para>
|
|
</question>
|
|
<answer>
|
|
<para>
|
|
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>
|
|
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>
|
|
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
|
|
<link linkend="book.password">native password hashing API</link>
|
|
whenever possible.
|
|
</para>
|
|
</answer>
|
|
</qandaentry>
|
|
<qandaentry xml:id="faq.passwords.salt">
|
|
<question>
|
|
<para>
|
|
What is a salt?
|
|
</para>
|
|
</question>
|
|
<answer>
|
|
<para>
|
|
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>
|
|
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
|
|
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>
|
|
<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>
|
|
</answer>
|
|
</qandaentry>
|
|
<qandaentry xml:id="faq.password.storing-salts">
|
|
<question>
|
|
<para>
|
|
How do I store my salts?
|
|
</para>
|
|
</question>
|
|
<answer>
|
|
<para>
|
|
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
|
|
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>
|
|
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
|
|
algorithm and salt required for future password verification.
|
|
</para>
|
|
<para>
|
|
<mediaobject>
|
|
<alt>
|
|
The components of the value returned by password_hash and crypt: in
|
|
order, the chosen algorithm, the algorithm's options, the salt used,
|
|
and the hashed password.
|
|
</alt>
|
|
<imageobject>
|
|
<imagedata fileref="en/faq/figures/crypt-text-rendered.svg" width="690" depth="192" format="SVG" />
|
|
</imageobject>
|
|
</mediaobject>
|
|
</para>
|
|
</answer>
|
|
</qandaentry>
|
|
</qandaset>
|
|
|
|
</chapter>
|
|
|
|
<!-- Keep this comment at the end of the file
|
|
Local variables:
|
|
mode: sgml
|
|
sgml-omittag:t
|
|
sgml-shorttag:t
|
|
sgml-minimize-attributes:nil
|
|
sgml-always-quote-attributes:t
|
|
sgml-indent-step:1
|
|
sgml-indent-data:t
|
|
indent-tabs-mode:nil
|
|
sgml-parent-document:nil
|
|
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
|
sgml-exposed-tags:nil
|
|
sgml-local-catalogs:nil
|
|
sgml-local-ecat-files:nil
|
|
End:
|
|
vim600: syn=xml fen fdm=syntax fdl=2 si
|
|
vim: et tw=78 syn=sgml
|
|
vi: ts=1 sw=1
|
|
-->
|