|
1 | 1 | <?xml version="1.0" encoding="utf-8"?> |
2 | 2 | <!-- $Revision$ --> |
3 | 3 | <chapter xml:id="faq.passwords" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink"> |
4 | | - <title>Safe Password Hashing</title> |
| 4 | + <title>Hashing passwords safely and securely</title> |
5 | 5 | <titleabbrev>Password Hashing</titleabbrev> |
6 | 6 |
|
7 | | - <para> |
| 7 | + <simpara> |
8 | 8 | This section explains the reasons behind using hashing functions |
9 | 9 | to secure passwords, as well as how to do so effectively. |
10 | | - </para> |
| 10 | + </simpara> |
11 | 11 |
|
12 | 12 | <qandaset> |
13 | 13 | <qandaentry xml:id="faq.passwords.hashing"> |
14 | 14 | <question> |
15 | | - <para> |
16 | | - Why should I hash passwords supplied by users of my application? |
17 | | - </para> |
| 15 | + <simpara> |
| 16 | + Why should passwords supplied by users be hashed? |
| 17 | + </simpara> |
18 | 18 | </question> |
19 | 19 | <answer> |
20 | | - <para> |
| 20 | + <simpara> |
21 | 21 | Password hashing is one of the most basic security considerations that |
22 | | - must be made when designing any application that accepts passwords |
23 | | - from users. Without hashing, any passwords that are stored in your |
24 | | - application's database can be stolen if the database is compromised, and |
25 | | - then immediately used to compromise not only your application, but also |
26 | | - the accounts of your users on other services, if they do not use |
| 22 | + must be made when designing any application or service that accepts passwords |
| 23 | + from users. Without hashing, any passwords that are stored |
| 24 | + can be stolen if the data store is compromised, and |
| 25 | + then immediately used to compromise not only the application or service, but also |
| 26 | + the accounts of users on other services, if they do not use |
27 | 27 | unique passwords. |
28 | | - </para> |
29 | | - <para> |
30 | | - By applying a hashing algorithm to your user's passwords before storing |
31 | | - them in your database, you make it implausible for any attacker to |
| 28 | + </simpara> |
| 29 | + <simpara> |
| 30 | + By applying a hashing algorithm to the user's passwords before storing |
| 31 | + them, it becomes implausible for any attacker to |
32 | 32 | determine the original password, while still being able to compare |
33 | 33 | the resulting hash to the original password in the future. |
34 | | - </para> |
35 | | - <para> |
| 34 | + </simpara> |
| 35 | + <simpara> |
36 | 36 | It is important to note, however, that hashing passwords only protects |
37 | | - them from being compromised in your data store, but does not necessarily |
38 | | - protect them from being intercepted by malicious code injected into your |
39 | | - application itself. |
40 | | - </para> |
| 37 | + them from being compromised in the data store, but does not necessarily |
| 38 | + protect them from being intercepted by malicious code injected into the |
| 39 | + application or service itself. |
| 40 | + </simpara> |
41 | 41 | </answer> |
42 | 42 | </qandaentry> |
43 | 43 | <qandaentry xml:id="faq.passwords.fasthash"> |
44 | 44 | <question> |
45 | | - <para> |
| 45 | + <simpara> |
46 | 46 | Why are common hashing functions such as <function>md5</function> and |
47 | 47 | <function>sha1</function> unsuitable for passwords? |
48 | | - </para> |
| 48 | + </simpara> |
49 | 49 | </question> |
50 | 50 | <answer> |
51 | | - <para> |
| 51 | + <simpara> |
52 | 52 | Hashing algorithms such as MD5, SHA1 and SHA256 are designed to be |
53 | 53 | very fast and efficient. With modern techniques and computer equipment, |
54 | | - it has become trivial to "brute force" the output of these algorithms, |
| 54 | + it has become trivial to <quote>brute force</quote> the output of these algorithms, |
55 | 55 | in order to determine the original input. |
56 | | - </para> |
57 | | - <para> |
58 | | - Because of how quickly a modern computer can "reverse" these hashing |
| 56 | + </simpara> |
| 57 | + <simpara> |
| 58 | + Because of how quickly a modern computer can <quote>reverse</quote> these hashing |
59 | 59 | algorithms, many security professionals strongly suggest against |
60 | 60 | their use for password hashing. |
61 | | - </para> |
| 61 | + </simpara> |
62 | 62 | </answer> |
63 | 63 | </qandaentry> |
64 | 64 | <qandaentry xml:id="faq.passwords.bestpractice"> |
65 | 65 | <question> |
66 | | - <para> |
67 | | - How should I hash my passwords, if the common hash functions are |
| 66 | + <simpara> |
| 67 | + How should passwords be hashed, if the common hash functions are |
68 | 68 | not suitable? |
69 | | - </para> |
| 69 | + </simpara> |
70 | 70 | </question> |
71 | 71 | <answer> |
72 | | - <para> |
| 72 | + <simpara> |
73 | 73 | When hashing passwords, the two most important considerations are the |
74 | 74 | computational expense, and the salt. The more computationally expensive |
75 | 75 | the hashing algorithm, the longer it will take to brute force its |
76 | 76 | output. |
77 | | - </para> |
78 | | - <para> |
| 77 | + </simpara> |
| 78 | + <simpara> |
79 | 79 | PHP provides |
80 | 80 | <link linkend="book.password">a native password hashing API</link> that |
81 | 81 | safely handles both <link linkend="function.password-hash">hashing</link> |
82 | 82 | and <link linkend="function.password-verify">verifying passwords</link> |
83 | 83 | in a secure manner. |
84 | | - </para> |
85 | | - <!-- TODO Drop mention of crypt? --> |
86 | | - <para> |
87 | | - Another option is the <function>crypt</function> function, which |
88 | | - supports several hashing algorithms. When using |
89 | | - this function, you are guaranteed that the algorithm you select is |
90 | | - available, as PHP contains native implementations of each supported |
91 | | - algorithm, in case one or more are not supported by your system. |
92 | | - </para> |
93 | | - <para> |
| 84 | + </simpara> |
| 85 | + <simpara> |
94 | 86 | The suggested algorithm to use when hashing passwords is Blowfish, which |
95 | 87 | is also the default used by the password hashing API, as it is |
96 | 88 | significantly more computationally expensive than MD5 or SHA1, while |
97 | 89 | still being scalable. |
98 | | - </para> |
99 | | - <para> |
100 | | - Note that if you are using <function>crypt</function> to verify a |
101 | | - password, you will need to take care to prevent timing attacks by using |
102 | | - a constant time string comparison. Neither PHP's |
103 | | - <link linkend="language.operators.comparison">== and === operators</link> |
104 | | - nor <function>strcmp</function> perform constant time string |
105 | | - comparisons. As <function>password_verify</function> will do this for |
106 | | - you, you are strongly encouraged to use the |
| 90 | + </simpara> |
| 91 | + <simpara> |
| 92 | + The <function>crypt</function> function is also available for password |
| 93 | + hashing, but it is only recommended for interoperability with other |
| 94 | + systems. |
| 95 | + Instead, it is strongly encouraged to use the |
107 | 96 | <link linkend="book.password">native password hashing API</link> |
108 | 97 | whenever possible. |
109 | | - </para> |
| 98 | + </simpara> |
110 | 99 | </answer> |
111 | 100 | </qandaentry> |
112 | 101 | <qandaentry xml:id="faq.passwords.salt"> |
113 | 102 | <question> |
114 | | - <para> |
| 103 | + <simpara> |
115 | 104 | What is a salt? |
116 | | - </para> |
| 105 | + </simpara> |
117 | 106 | </question> |
118 | 107 | <answer> |
119 | | - <para> |
| 108 | + <simpara> |
120 | 109 | A cryptographic salt is data which is applied during the hashing process |
121 | 110 | in order to eliminate the possibility of the output being looked up |
122 | 111 | in a list of pre-calculated pairs of hashes and their input, known as |
123 | 112 | a rainbow table. |
124 | | - </para> |
125 | | - <para> |
| 113 | + </simpara> |
| 114 | + <simpara> |
126 | 115 | In more simple terms, a salt is a bit of additional data which makes |
127 | | - your hashes significantly more difficult to crack. There are a number of |
| 116 | + hashes significantly more difficult to crack. There are a number of |
128 | 117 | services online which provide extensive lists of pre-computed hashes, as |
129 | 118 | well as the original input for those hashes. The use of a salt makes it |
130 | 119 | implausible or impossible to find the resulting hash in one of these |
131 | 120 | lists. |
132 | | - </para> |
133 | | - <para> |
| 121 | + </simpara> |
| 122 | + <simpara> |
134 | 123 | <function>password_hash</function> will create a random salt if one |
135 | 124 | isn't provided, and this is generally the easiest and most secure |
136 | 125 | approach. |
137 | | - </para> |
| 126 | + </simpara> |
138 | 127 | </answer> |
139 | 128 | </qandaentry> |
140 | 129 | <qandaentry xml:id="faq.password.storing-salts"> |
141 | 130 | <question> |
142 | | - <para> |
143 | | - How do I store my salts? |
144 | | - </para> |
| 131 | + <simpara> |
| 132 | + How are salts stored? |
| 133 | + </simpara> |
145 | 134 | </question> |
146 | 135 | <answer> |
147 | | - <para> |
| 136 | + <simpara> |
148 | 137 | When using <function>password_hash</function> or |
149 | 138 | <function>crypt</function>, the return value includes the salt as part |
150 | | - of the generated hash. This value should be stored verbatim in your |
| 139 | + of the generated hash. This value should be stored verbatim in the |
151 | 140 | database, as it includes information about the hash function that was |
152 | 141 | used and can then be given directly to |
153 | | - <function>password_verify</function> or <function>crypt</function> when |
154 | | - verifying passwords. |
155 | | - </para> |
156 | | - <para> |
| 142 | + <function>password_verify</function> when verifying passwords. |
| 143 | + </simpara> |
| 144 | + <warning> |
| 145 | + <simpara> |
| 146 | + <function>password_verify</function> should always be used instead |
| 147 | + of re-hashing and comparing the result to a stored hash in order |
| 148 | + to avoid timing attacks. |
| 149 | + </simpara> |
| 150 | + </warning> |
| 151 | + <simpara> |
157 | 152 | The following diagram shows the format of a return value from |
158 | | - <function>crypt</function> or <function>password_hash</function>. As you |
159 | | - can see, they are self-contained, with all the information on the |
| 153 | + <function>crypt</function> or <function>password_hash</function>. As can |
| 154 | + be seen, they are self-contained, with all the information on the |
160 | 155 | algorithm and salt required for future password verification. |
161 | | - </para> |
| 156 | + </simpara> |
162 | 157 | <para> |
163 | 158 | <mediaobject> |
164 | 159 | <alt> |
|
0 commit comments