uTools-Manuals/docs/php/password_hash.html
2019-04-28 19:00:34 +08:00

358 lines
20 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>创建密码的散列hash</title>
</head>
<body class="docs"><div id="layout">
<div id="layout-content"><div id="function.password-hash" class="refentry">
<div class="refnamediv">
<h1 class="refname">password_hash</h1>
<p class="verinfo">(PHP 5 &gt;= 5.5.0, PHP 7)</p><p class="refpurpose"><span class="refname">password_hash</span> &mdash; <span class="dc-title">创建密码的散列hash</span></p>
</div>
<div class="refsect1 description" id="refsect1-function.password-hash-description">
<h3 class="title">说明</h3>
<div class="methodsynopsis dc-description">
<span class="methodname"><strong>password_hash</strong></span>
( <span class="methodparam"><span class="type">string</span> <code class="parameter">$password</code></span>
, <span class="methodparam"><span class="type">int</span> <code class="parameter">$algo</code></span>
[, <span class="methodparam"><span class="type">array</span> <code class="parameter">$options</code></span>
] ) : <span class="type">string</span></div>
<p class="para rdfs-comment">
<span class="function"><strong>password_hash()</strong></span> 使用足够强度的单向散列算法创建密码的散列hash
<span class="function"><strong>password_hash()</strong></span> 兼容 <span class="function"><a href="crypt.html" class="function">crypt()</a></span>
所以, <span class="function"><a href="crypt.html" class="function">crypt()</a></span> 创建的密码散列也可用于
<span class="function"><strong>password_hash()</strong></span>
</p>
<p class="simpara">
当前支持的算法:
</p>
<p class="para">
<ul class="itemizedlist">
<li class="listitem">
<span class="simpara">
<strong><code>PASSWORD_DEFAULT</code></strong> - 使用 bcrypt 算法 (PHP 5.5.0 默认)。
注意,该常量会随着 PHP 加入更新更高强度的算法而改变。
所以,使用此常量生成结果的长度将在未来有变化。
因此数据库里储存结果的列可超过60个字符最好是255个字符
</span>
</li>
<li class="listitem">
<span class="simpara">
<strong><code>PASSWORD_BCRYPT</code></strong> - 使用 <strong><code>CRYPT_BLOWFISH</code></strong> 算法创建散列。
这会产生兼容使用 &quot;$2y$&quot;<span class="function"><a href="crypt.html" class="function">crypt()</a></span>
结果将会是 60 个字符的字符串, 或者在失败时返回 <strong><code>FALSE</code></strong>
</span>
</li>
<li class="listitem">
<span class="simpara">
<strong><code>PASSWORD_ARGON2I</code></strong> - 使用 Argon2 散列算法创建散列。
</span>
</li>
</ul>
</p>
<p class="simpara">
<strong><code>PASSWORD_BCRYPT</code></strong> 支持的选项:
</p>
<p class="para">
<ul class="itemizedlist">
<li class="listitem">
<p class="para">
<em>salt</em>(<span class="type"><a href="language.types.string.html" class="type string">string</a></span>) - 手动提供散列密码的盐值salt。这将避免自动生成盐值salt
</p>
<p class="para">
省略此值后,<span class="function"><strong>password_hash()</strong></span> 会为每个密码散列自动生成随机的盐值。这种操作是有意的模式。
</p>
<div class="warning"><strong class="warning">Warning</strong>
<p class="para">
盐值salt选项从 PHP 7.0.0 开始被废弃deprecated了。
现在最好选择简单的使用默认产生的盐值。
</p>
</div>
</li>
<li class="listitem">
<p class="para">
<em>cost</em> (<span class="type"><a href="language.types.integer.html" class="type integer">integer</a></span>) _ 代表算法使用的 cost。<span class="function"><a href="crypt.html" class="function">crypt()</a></span> 页面上有 cost 值的例子。
</p>
<p class="para">
省略时,默认值是 <em>10</em>
这个 cost 是个不错的底线,但也许可以根据自己硬件的情况,加大这个值。
</p>
</li>
</ul>
</p>
<p class="simpara">
<strong><code>PASSWORD_ARGON2I</code></strong> 支持的选项:
</p>
<p class="para">
<ul class="itemizedlist">
<li class="listitem">
<p class="para">
<em>memory_cost</em> (<span class="type"><a href="language.types.integer.html" class="type integer">integer</a></span>) - 计算 Argon2 散列时的最大内存(单位:字节 byte。默认值 <strong><code>PASSWORD_ARGON2_DEFAULT_MEMORY_COST</code></strong>
</p>
</li>
<li class="listitem">
<p class="para">
<em>time_cost</em> (<span class="type"><a href="language.types.integer.html" class="type integer">integer</a></span>) - 计算 Argon2 散列时最多的时间。默认值: <strong><code>PASSWORD_ARGON2_DEFAULT_TIME_COST</code></strong>
</p>
</li>
<li class="listitem">
<p class="para">
<em>threads</em> (<span class="type"><a href="language.types.integer.html" class="type integer">integer</a></span>) - 计算 Argon2 散列时最多的线程数。默认值: <strong><code>PASSWORD_ARGON2_DEFAULT_THREADS</code></strong>
</p>
</li>
</ul>
</p>
</div>
<div class="refsect1 parameters" id="refsect1-function.password-hash-parameters">
<h3 class="title">参数</h3>
<dl>
<dt>
<code class="parameter">password</code></dt>
<dd>
<p class="para">
用户的密码。
</p>
<div class="caution"><strong class="caution">Caution</strong>
<p class="para">
使用<strong><code>PASSWORD_BCRYPT</code></strong> 做算法,将使 <code class="parameter">password</code> 参数最长为72个字符超过会被截断。
</p>
</div>
</dd>
<dt>
<code class="parameter">algo</code></dt>
<dd>
<p class="para">
一个用来在散列密码时指示算法的<a href="password.constants.html" class="link">密码算法常量</a>
</p>
</dd>
<dt>
<code class="parameter">options</code></dt>
<dd>
<p class="para">
一个包含有选项的关联数组。目前支持两个选项:<em>salt</em>,在散列密码时加的盐(干扰字符串),以及<em>cost</em>,用来指明算法递归的层数。这两个值的例子可在 <span class="function"><a href="crypt.html" class="function">crypt()</a></span> 页面找到。
</p>
<p class="para">
省略后,将使用随机盐值与默认 cost。
</p>
</dd>
</dl>
</div>
<div class="refsect1 returnvalues" id="refsect1-function.password-hash-returnvalues">
<h3 class="title">返回值</h3>
<p class="para">
返回散列后的密码, 或者在失败时返回 <strong><code>FALSE</code></strong>
</p>
<p class="para">
使用的算法、cost 和盐值作为散列的一部分返回。所以验证散列值的所有信息都已经包含在内。
这使 <span class="function"><a href="password_verify.html" class="function">password_verify()</a></span> 函数验证的时候,不需要额外储存盐值或者算法的信息。
</p>
</div>
<div class="refsect1 examples" id="refsect1-function.password-hash-examples">
<h3 class="title">范例</h3>
<p class="para">
<div class="example" id="example-956">
<p><strong>Example #1 <span class="function"><strong>password_hash()</strong></span> 例子</strong></p>
<div class="example-contents">
<div class="phpcode"><pre><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #FF8000">/**<br />&nbsp;*&nbsp;我们想要使用默认算法散列密码<br />&nbsp;*&nbsp;当前是&nbsp;BCRYPT并会产生&nbsp;60&nbsp;个字符的结果。<br />&nbsp;*<br />&nbsp;*&nbsp;请注意,随时间推移,默认算法可能会有变化,<br />&nbsp;*&nbsp;所以需要储存的空间能够超过&nbsp;60&nbsp;255字不错<br />&nbsp;*/<br /></span><span style="color: #007700">echo&nbsp;</span><span style="color: #0000BB">password_hash</span><span style="color: #007700">(</span><span style="color: #DD0000">"rasmuslerdorf"</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">PASSWORD_DEFAULT</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</pre></div>
</div>
<div class="example-contents"><p>以上例程的输出类似于:</p></div>
<div class="example-contents screen">
<div class="cdata"><pre>
$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a
</pre></div>
</div>
</div>
</p>
<p class="para">
<div class="example" id="example-957">
<p><strong>Example #2 <span class="function"><strong>password_hash()</strong></span> 手动设置 cost 的例子</strong></p>
<div class="example-contents">
<div class="phpcode"><pre><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #FF8000">/**<br />&nbsp;*&nbsp;在这个案例里,我们为&nbsp;BCRYPT&nbsp;增加&nbsp;cost&nbsp;&nbsp;12。<br />&nbsp;*&nbsp;注意,我们已经切换到了,将始终产生&nbsp;60&nbsp;个字符。<br />&nbsp;*/<br /></span><span style="color: #0000BB">$options&nbsp;</span><span style="color: #007700">=&nbsp;[<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #DD0000">'cost'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">12</span><span style="color: #007700">,<br />];<br />echo&nbsp;</span><span style="color: #0000BB">password_hash</span><span style="color: #007700">(</span><span style="color: #DD0000">"rasmuslerdorf"</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">PASSWORD_BCRYPT</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">$options</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</pre></div>
</div>
<div class="example-contents"><p>以上例程的输出类似于:</p></div>
<div class="example-contents screen">
<div class="cdata"><pre>
$2y$12$QjSH496pcT5CEbzjD/vtVeH03tfHKFy36d4J0Ltp3lRtee9HDxY3K
</pre></div>
</div>
</div>
</p>
<p class="para">
<div class="example" id="example-958">
<p><strong>Example #3 <span class="function"><strong>password_hash()</strong></span> 手动设置盐值的例子</strong></p>
<div class="example-contents">
<div class="phpcode"><pre><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #FF8000">/**<br />&nbsp;*&nbsp;注意,这里的盐值是随机产生的。<br />&nbsp;*&nbsp;永远都不要使用固定盐值,或者不是随机生成的盐值。<br />&nbsp;*<br />&nbsp;*&nbsp;绝大多数情况下,可以让&nbsp;password_hash&nbsp;generate&nbsp;为你自动产生随机盐值<br />&nbsp;*/<br /></span><span style="color: #0000BB">$options&nbsp;</span><span style="color: #007700">=&nbsp;[<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #DD0000">'cost'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">11</span><span style="color: #007700">,<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #DD0000">'salt'&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">mcrypt_create_iv</span><span style="color: #007700">(</span><span style="color: #0000BB">22</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">MCRYPT_DEV_URANDOM</span><span style="color: #007700">),<br />];<br />echo&nbsp;</span><span style="color: #0000BB">password_hash</span><span style="color: #007700">(</span><span style="color: #DD0000">"rasmuslerdorf"</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">PASSWORD_BCRYPT</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">$options</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</pre></div>
</div>
<div class="example-contents"><p>以上例程的输出类似于:</p></div>
<div class="example-contents screen">
<div class="cdata"><pre>
$2y$11$q5MkhSBtlsJcNEVsYh64a.aCluzHnGog7TQAKVmQwO9C8xb.t89F.
</pre></div>
</div>
</div>
</p>
<p class="para">
<div class="example" id="example-959">
<p><strong>Example #4 寻找最佳 cost 的 <span class="function"><strong>password_hash()</strong></span> 例子</strong></p>
<div class="example-contents">
<div class="phpcode"><pre><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #FF8000">/**<br />&nbsp;*&nbsp;这个例子对服务器做了基准测试benchmark检测服务器能承受多高的&nbsp;cost<br />&nbsp;*&nbsp;在不明显拖慢服务器的情况下可以设置最高的值<br />&nbsp;*&nbsp;8-10&nbsp;是个不错的底线,在服务器够快的情况下,越高越好。<br />&nbsp;*&nbsp;以下代码目标为&nbsp;&nbsp;&nbsp;50&nbsp;毫秒milliseconds<br />&nbsp;*&nbsp;适合系统处理交互登录。<br />&nbsp;*/<br /></span><span style="color: #0000BB">$timeTarget&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">0.05</span><span style="color: #007700">;&nbsp;</span><span style="color: #FF8000">//&nbsp;50&nbsp;毫秒milliseconds&nbsp;<br /><br /></span><span style="color: #0000BB">$cost&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">8</span><span style="color: #007700">;<br />do&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$cost</span><span style="color: #007700">++;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$start&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">microtime</span><span style="color: #007700">(</span><span style="color: #0000BB">true</span><span style="color: #007700">);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">password_hash</span><span style="color: #007700">(</span><span style="color: #DD0000">"test"</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">PASSWORD_BCRYPT</span><span style="color: #007700">,&nbsp;[</span><span style="color: #DD0000">"cost"&nbsp;</span><span style="color: #007700">=&gt;&nbsp;</span><span style="color: #0000BB">$cost</span><span style="color: #007700">]);<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000BB">$end&nbsp;</span><span style="color: #007700">=&nbsp;</span><span style="color: #0000BB">microtime</span><span style="color: #007700">(</span><span style="color: #0000BB">true</span><span style="color: #007700">);<br />}&nbsp;while&nbsp;((</span><span style="color: #0000BB">$end&nbsp;</span><span style="color: #007700">-&nbsp;</span><span style="color: #0000BB">$start</span><span style="color: #007700">)&nbsp;&lt;&nbsp;</span><span style="color: #0000BB">$timeTarget</span><span style="color: #007700">);<br /><br />echo&nbsp;</span><span style="color: #DD0000">"Appropriate&nbsp;Cost&nbsp;Found:&nbsp;"&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">$cost</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</pre></div>
</div>
<div class="example-contents"><p>以上例程的输出类似于:</p></div>
<div class="example-contents screen">
<div class="cdata"><pre>
Appropriate Cost Found: 10
</pre></div>
</div>
</div>
</p>
<p class="para">
<div class="example" id="openssl_spki_export_challenge.example.basic">
<p><strong>Example #5 使用 Argon2 的<span class="function"><strong>password_hash()</strong></span>例子</strong></p>
<div class="example-contents">
<div class="phpcode"><pre><span style="color: #000000">
<span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">echo&nbsp;</span><span style="color: #DD0000">'Argon2&nbsp;hash:&nbsp;'&nbsp;</span><span style="color: #007700">.&nbsp;</span><span style="color: #0000BB">password_hash</span><span style="color: #007700">(</span><span style="color: #DD0000">'rasmuslerdorf'</span><span style="color: #007700">,&nbsp;</span><span style="color: #0000BB">PASSWORD_ARGON2I</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">?&gt;</span>
</span>
</pre></div>
</div>
<div class="example-contents"><p>以上例程的输出类似于:</p></div>
<div class="example-contents screen">
<div class="cdata"><pre>
Argon2 hash: $argon2i$v=19$m=1024,t=2,p=2$YzJBSzV4TUhkMzc3d3laeg$zqU/1IN0/AogfP4cmSJI1vc8lpXRW9/S0sYY2i2jHT0
</pre></div>
</div>
</div>
</p>
</div>
<div class="refsect1 notes" id="refsect1-function.password-hash-notes">
<h3 class="title">注释</h3>
<div class="caution"><strong class="caution">Caution</strong>
<p class="para">
强烈建议不要自己为这个函数生成盐值salt。只要不设置它会自动创建安全的盐值。
</p>
<p class="para">
就像以上提及的,在 PHP 7.0 提供 <em>salt</em>选项会导致废弃deprecation警告。
未来的 PHP 发行版里,手动提供盐值的功能可能会被删掉。
</p>
</div>
<blockquote class="note"><p><strong class="note">Note</strong>:
<p class="para">
在交互的系统上,推荐在自己的服务器上测试此函数,调整 cost 参数直至函数时间开销小于 100 毫秒milliseconds
上面脚本的例子会帮助选择合适硬件的最佳 cost。
</p>
</p></blockquote>
<blockquote class="note"><p><strong class="note">Note</strong>:
<span class="simpara">
这个函数更新支持的算法时(或修改默认算法),必定会遵守以下规则:
</span>
<p class="para">
<ul class="itemizedlist">
<li class="listitem">
<span class="simpara">
任何内核中的新算法必须在经历一次 PHP 完整发行才能成为默认算法。
比如,在 PHP 7.5.5 中添加的新算法,在 PHP 7.7 之前不能成为默认算法
(由于 7.6 是第一个完整发行版)。
但如果是在 7.6.0 里添加的不同算法,在 7.7.0 里也可以成为默认算法。
</span>
</li>
<li class="listitem">
<span class="simpara">
仅仅允许在完整发行版中修改默认算法(比如 7.3.0, 8.0.0,等等),不能是在修订版。
唯一的例外是:在当前默认算法里发现了紧急的安全威胁。
</span>
</li>
</ul>
</p>
</p></blockquote>
</div>
<div class="refsect1 changelog" id="refsect1-function.password-hash-changelog">
<h3 class="title">更新日志</h3>
<p class="para">
<table class="doctable informaltable">
<thead>
<tr>
<th>版本</th>
<th>说明</th>
</tr>
</thead>
<tbody class="tbody">
<tr>
<td>7.2.0</td>
<td>
添加 <strong><code>PASSWORD_ARGON2I</code></strong>,支持 Argon2 密码散列算法。
</td>
</tr>
</tbody>
</table>
</p>
</div>
<div class="refsect1 seealso" id="refsect1-function.password-hash-seealso">
<h3 class="title">参见</h3>
<p class="para">
<ul class="simplelist">
<li class="member"><span class="function"><a href="password_verify.html" class="function" rel="rdfs-seeAlso">password_verify()</a> - 验证密码是否和散列值匹配</span></li>
<li class="member"><span class="function"><a href="crypt.html" class="function" rel="rdfs-seeAlso">crypt()</a> - 单向字符串散列</span></li>
<li class="member"><a href="https://github.com/ircmaxell/password_compat" class="link external">&raquo;&nbsp;用户的使用</a></li>
</ul>
</p>
</div>
</div></div></div></body></html>