Files
google-apis-rs/ring/pbkdf2/index.html
2021-04-02 00:20:57 +08:00

104 lines
16 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><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="API documentation for the Rust `pbkdf2` mod in crate `ring`."><meta name="keywords" content="rust, rustlang, rust-lang, pbkdf2"><title>ring::pbkdf2 - Rust</title><link rel="stylesheet" type="text/css" href="../../normalize.css"><link rel="stylesheet" type="text/css" href="../../rustdoc.css" id="mainThemeStyle"><link rel="stylesheet" type="text/css" href="../../light.css" id="themeStyle"><link rel="stylesheet" type="text/css" href="../../dark.css" disabled ><link rel="stylesheet" type="text/css" href="../../ayu.css" disabled ><script id="default-settings"></script><script src="../../storage.js"></script><noscript><link rel="stylesheet" href="../../noscript.css"></noscript><link rel="icon" type="image/svg+xml" href="../../favicon.svg">
<link rel="alternate icon" type="image/png" href="../../favicon-16x16.png">
<link rel="alternate icon" type="image/png" href="../../favicon-32x32.png"><style type="text/css">#crate-search{background-image:url("../../down-arrow.svg");}</style></head><body class="rustdoc mod"><!--[if lte IE 8]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="sidebar"><div class="sidebar-menu">&#9776;</div><a href='../../ring/index.html'><div class='logo-container rust-logo'><img src='../../rust-logo.png' alt='logo'></div></a><p class="location">Module pbkdf2</p><div class="sidebar-elems"><div class="block items"><ul><li><a href="#structs">Structs</a></li><li><a href="#statics">Statics</a></li><li><a href="#functions">Functions</a></li></ul></div><p class="location"><a href="../index.html">ring</a></p><div id="sidebar-vars" data-name="pbkdf2" data-ty="mod" data-relpath="../"></div><script defer src="../sidebar-items.js"></script></div></nav><div class="theme-picker"><button id="theme-picker" aria-label="Pick another theme!" aria-haspopup="menu"><img src="../../brush.svg" width="18" alt="Pick another theme!"></button><div id="theme-choices" role="menu"></div></div><script src="../../theme.js"></script><nav class="sub"><form class="search-form"><div class="search-container"><div><select id="crate-search"><option value="All crates">All crates</option></select><input class="search-input" name="search" disabled autocomplete="off" spellcheck="false" placeholder="Click or press S to search, ? for more options…" type="search"></div><button type="button" class="help-button">?</button>
<a id="settings-menu" href="../../settings.html"><img src="../../wheel.svg" width="18" alt="Change settings"></a></div></form></nav><section id="main" class="content"><h1 class="fqn"><span class="in-band">Module <a href="../index.html">ring</a>::<wbr><a class="mod" href="">pbkdf2</a></span><span class="out-of-band"><span id="render-detail"><a id="toggle-all-docs" href="javascript:void(0)" title="collapse all docs">[<span class="inner">&#x2212;</span>]</a></span><a class="srclink" href="../../src/ring/pbkdf2.rs.html#15-272" title="goto source code">[src]</a></span></h1><div class="docblock"><p>PBKDF2 derivation and verification.</p>
<p>Use <code>derive</code> to derive PBKDF2 outputs. Use <code>verify</code> to verify secret
against previously-derived outputs.</p>
<p>PBKDF2 is specified in <a href="https://tools.ietf.org/html/rfc2898#section-5.2">RFC 2898 Section 5.2</a> with test vectors given in
<a href="https://tools.ietf.org/html/rfc6070">RFC 6070</a>. See also <a href="http://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf">NIST Special Publication 800-132</a>.</p>
<h1 id="examples" class="section-header"><a href="#examples">Examples</a></h1><h2 id="password-database-example" class="section-header"><a href="#password-database-example">Password Database Example</a></h2>
<div class="example-wrap"><pre class="rust rust-example-rendered">
<span class="kw">use</span> <span class="ident">ring</span>::{<span class="ident">digest</span>, <span class="ident">pbkdf2</span>};
<span class="kw">use</span> <span class="ident">std</span>::{<span class="ident">collections</span>::<span class="ident">HashMap</span>, <span class="ident">num</span>::<span class="ident">NonZeroU32</span>};
<span class="kw">static</span> <span class="ident">PBKDF2_ALG</span>: <span class="ident">pbkdf2</span>::<span class="ident">Algorithm</span> <span class="op">=</span> <span class="ident">pbkdf2</span>::<span class="ident">PBKDF2_HMAC_SHA256</span>;
<span class="kw">const</span> <span class="ident">CREDENTIAL_LEN</span>: <span class="ident">usize</span> <span class="op">=</span> <span class="ident">digest</span>::<span class="ident">SHA256_OUTPUT_LEN</span>;
<span class="kw">pub</span> <span class="kw">type</span> <span class="ident">Credential</span> <span class="op">=</span> [<span class="ident">u8</span>; <span class="ident">CREDENTIAL_LEN</span>];
<span class="kw">enum</span> <span class="ident">Error</span> {
<span class="ident">WrongUsernameOrPassword</span>
}
<span class="kw">struct</span> <span class="ident">PasswordDatabase</span> {
<span class="ident">pbkdf2_iterations</span>: <span class="ident">NonZeroU32</span>,
<span class="ident">db_salt_component</span>: [<span class="ident">u8</span>; <span class="number">16</span>],
<span class="comment">// Normally this would be a persistent database.</span>
<span class="ident">storage</span>: <span class="ident">HashMap</span><span class="op">&lt;</span><span class="ident">String</span>, <span class="ident">Credential</span><span class="op">&gt;</span>,
}
<span class="kw">impl</span> <span class="ident">PasswordDatabase</span> {
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">store_password</span>(<span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="self">self</span>, <span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="ident">password</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) {
<span class="kw">let</span> <span class="ident">salt</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">salt</span>(<span class="ident">username</span>);
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">to_store</span>: <span class="ident">Credential</span> <span class="op">=</span> [<span class="number">0u8</span>; <span class="ident">CREDENTIAL_LEN</span>];
<span class="ident">pbkdf2</span>::<span class="ident">derive</span>(<span class="ident">PBKDF2_ALG</span>, <span class="self">self</span>.<span class="ident">pbkdf2_iterations</span>, <span class="kw-2">&amp;</span><span class="ident">salt</span>,
<span class="ident">password</span>.<span class="ident">as_bytes</span>(), <span class="kw-2">&amp;</span><span class="kw-2">mut</span> <span class="ident">to_store</span>);
<span class="self">self</span>.<span class="ident">storage</span>.<span class="ident">insert</span>(<span class="ident">String</span>::<span class="ident">from</span>(<span class="ident">username</span>), <span class="ident">to_store</span>);
}
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">verify_password</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="ident">attempted_password</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>)
<span class="op">-</span><span class="op">&gt;</span> <span class="prelude-ty">Result</span><span class="op">&lt;</span>(), <span class="ident">Error</span><span class="op">&gt;</span> {
<span class="kw">match</span> <span class="self">self</span>.<span class="ident">storage</span>.<span class="ident">get</span>(<span class="ident">username</span>) {
<span class="prelude-val">Some</span>(<span class="ident">actual_password</span>) <span class="op">=</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">salt</span> <span class="op">=</span> <span class="self">self</span>.<span class="ident">salt</span>(<span class="ident">username</span>);
<span class="ident">pbkdf2</span>::<span class="ident">verify</span>(<span class="ident">PBKDF2_ALG</span>, <span class="self">self</span>.<span class="ident">pbkdf2_iterations</span>, <span class="kw-2">&amp;</span><span class="ident">salt</span>,
<span class="ident">attempted_password</span>.<span class="ident">as_bytes</span>(),
<span class="ident">actual_password</span>)
.<span class="ident">map_err</span>(<span class="op">|</span><span class="kw">_</span><span class="op">|</span> <span class="ident">Error</span>::<span class="ident">WrongUsernameOrPassword</span>)
},
<span class="prelude-val">None</span> <span class="op">=</span><span class="op">&gt;</span> <span class="prelude-val">Err</span>(<span class="ident">Error</span>::<span class="ident">WrongUsernameOrPassword</span>)
}
}
<span class="comment">// The salt should have a user-specific component so that an attacker</span>
<span class="comment">// cannot crack one password for multiple users in the database. It</span>
<span class="comment">// should have a database-unique component so that an attacker cannot</span>
<span class="comment">// crack the same user&#39;s password across databases in the unfortunate</span>
<span class="comment">// but common case that the user has used the same password for</span>
<span class="comment">// multiple systems.</span>
<span class="kw">fn</span> <span class="ident">salt</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) <span class="op">-</span><span class="op">&gt;</span> <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">u8</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">salt</span> <span class="op">=</span> <span class="ident">Vec</span>::<span class="ident">with_capacity</span>(<span class="self">self</span>.<span class="ident">db_salt_component</span>.<span class="ident">len</span>() <span class="op">+</span>
<span class="ident">username</span>.<span class="ident">as_bytes</span>().<span class="ident">len</span>());
<span class="ident">salt</span>.<span class="ident">extend</span>(<span class="self">self</span>.<span class="ident">db_salt_component</span>.<span class="ident">as_ref</span>());
<span class="ident">salt</span>.<span class="ident">extend</span>(<span class="ident">username</span>.<span class="ident">as_bytes</span>());
<span class="ident">salt</span>
}
}
<span class="kw">fn</span> <span class="ident">main</span>() {
<span class="comment">// Normally these parameters would be loaded from a configuration file.</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">db</span> <span class="op">=</span> <span class="ident">PasswordDatabase</span> {
<span class="ident">pbkdf2_iterations</span>: <span class="ident">NonZeroU32</span>::<span class="ident">new</span>(<span class="number">100_000</span>).<span class="ident">unwrap</span>(),
<span class="ident">db_salt_component</span>: [
<span class="comment">// This value was generated from a secure PRNG.</span>
<span class="number">0xd6</span>, <span class="number">0x26</span>, <span class="number">0x98</span>, <span class="number">0xda</span>, <span class="number">0xf4</span>, <span class="number">0xdc</span>, <span class="number">0x50</span>, <span class="number">0x52</span>,
<span class="number">0x24</span>, <span class="number">0xf2</span>, <span class="number">0x27</span>, <span class="number">0xd1</span>, <span class="number">0xfe</span>, <span class="number">0x39</span>, <span class="number">0x01</span>, <span class="number">0x8a</span>
],
<span class="ident">storage</span>: <span class="ident">HashMap</span>::<span class="ident">new</span>(),
};
<span class="ident">db</span>.<span class="ident">store_password</span>(<span class="string">&quot;alice&quot;</span>, <span class="string">&quot;@74d7]404j|W}6u&quot;</span>);
<span class="comment">// An attempt to log in with the wrong password fails.</span>
<span class="macro">assert</span><span class="macro">!</span>(<span class="ident">db</span>.<span class="ident">verify_password</span>(<span class="string">&quot;alice&quot;</span>, <span class="string">&quot;wrong password&quot;</span>).<span class="ident">is_err</span>());
<span class="comment">// Normally there should be an expoentially-increasing delay between</span>
<span class="comment">// attempts to further protect against online attacks.</span>
<span class="comment">// An attempt to log in with the right password succeeds.</span>
<span class="macro">assert</span><span class="macro">!</span>(<span class="ident">db</span>.<span class="ident">verify_password</span>(<span class="string">&quot;alice&quot;</span>, <span class="string">&quot;@74d7]404j|W}6u&quot;</span>).<span class="ident">is_ok</span>());
}</pre></div>
</div><h2 id="structs" class="section-header"><a href="#structs">Structs</a></h2>
<table><tr class="module-item"><td><a class="struct" href="struct.Algorithm.html" title="ring::pbkdf2::Algorithm struct">Algorithm</a></td><td class="docblock-short"><p>A PBKDF2 algorithm.</p>
</td></tr></table><h2 id="statics" class="section-header"><a href="#statics">Statics</a></h2>
<table><tr class="module-item"><td><a class="static" href="static.PBKDF2_HMAC_SHA1.html" title="ring::pbkdf2::PBKDF2_HMAC_SHA1 static">PBKDF2_HMAC_SHA1</a></td><td class="docblock-short"><p>PBKDF2 using HMAC-SHA1.</p>
</td></tr><tr class="module-item"><td><a class="static" href="static.PBKDF2_HMAC_SHA256.html" title="ring::pbkdf2::PBKDF2_HMAC_SHA256 static">PBKDF2_HMAC_SHA256</a></td><td class="docblock-short"><p>PBKDF2 using HMAC-SHA256.</p>
</td></tr><tr class="module-item"><td><a class="static" href="static.PBKDF2_HMAC_SHA384.html" title="ring::pbkdf2::PBKDF2_HMAC_SHA384 static">PBKDF2_HMAC_SHA384</a></td><td class="docblock-short"><p>PBKDF2 using HMAC-SHA384.</p>
</td></tr><tr class="module-item"><td><a class="static" href="static.PBKDF2_HMAC_SHA512.html" title="ring::pbkdf2::PBKDF2_HMAC_SHA512 static">PBKDF2_HMAC_SHA512</a></td><td class="docblock-short"><p>PBKDF2 using HMAC-SHA512.</p>
</td></tr></table><h2 id="functions" class="section-header"><a href="#functions">Functions</a></h2>
<table><tr class="module-item"><td><a class="fn" href="fn.derive.html" title="ring::pbkdf2::derive fn">derive</a></td><td class="docblock-short"><p>Fills <code>out</code> with the key derived using PBKDF2 with the given inputs.</p>
</td></tr><tr class="module-item"><td><a class="fn" href="fn.verify.html" title="ring::pbkdf2::verify fn">verify</a></td><td class="docblock-short"><p>Verifies that a previously-derived (e.g., using <code>derive</code>) PBKDF2 value
matches the PBKDF2 value derived from the other inputs.</p>
</td></tr></table></section><section id="search" class="content hidden"></section><section class="footer"></section><div id="rustdoc-vars" data-root-path="../../" data-current-crate="ring"></div>
<script src="../../main.js"></script><script defer src="../../search-index.js"></script></body></html>