summaryrefslogtreecommitdiffstats
path: root/third_party/rust/rust-argon2
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/rust-argon2
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/rust-argon2')
-rw-r--r--third_party/rust/rust-argon2/.cargo-checksum.json1
-rw-r--r--third_party/rust/rust-argon2/CHANGELOG.md44
-rw-r--r--third_party/rust/rust-argon2/Cargo.toml36
-rw-r--r--third_party/rust/rust-argon2/LICENSE-APACHE201
-rw-r--r--third_party/rust/rust-argon2/LICENSE-MIT22
-rw-r--r--third_party/rust/rust-argon2/README.md85
-rw-r--r--third_party/rust/rust-argon2/src/argon2.rs717
-rw-r--r--third_party/rust/rust-argon2/src/block.rs142
-rw-r--r--third_party/rust/rust-argon2/src/common.rs92
-rw-r--r--third_party/rust/rust-argon2/src/config.rs105
-rw-r--r--third_party/rust/rust-argon2/src/context.rs213
-rw-r--r--third_party/rust/rust-argon2/src/core.rs474
-rw-r--r--third_party/rust/rust-argon2/src/decoded.rs35
-rw-r--r--third_party/rust/rust-argon2/src/encoding.rs401
-rw-r--r--third_party/rust/rust-argon2/src/error.rs119
-rw-r--r--third_party/rust/rust-argon2/src/lib.rs103
-rw-r--r--third_party/rust/rust-argon2/src/memory.rs120
-rw-r--r--third_party/rust/rust-argon2/src/result.rs13
-rw-r--r--third_party/rust/rust-argon2/src/thread_mode.rs56
-rw-r--r--third_party/rust/rust-argon2/src/variant.rs159
-rw-r--r--third_party/rust/rust-argon2/src/version.rs97
-rw-r--r--third_party/rust/rust-argon2/tests/integration_test.rs1076
22 files changed, 4311 insertions, 0 deletions
diff --git a/third_party/rust/rust-argon2/.cargo-checksum.json b/third_party/rust/rust-argon2/.cargo-checksum.json
new file mode 100644
index 0000000000..cb81f8f153
--- /dev/null
+++ b/third_party/rust/rust-argon2/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"01442e11a70787ec85073f75c29ac23e84821a3e6aabca9423f68e507096463f","Cargo.toml":"d08e0d7065ae57f095e31d01210c0a39c6fc43c7bf19af79fbd2352d9fff3838","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"26b997d1a1496df49cb1ad2cbe024714cd9126543c18e1bc6c7bbca1b3dc42b6","README.md":"af8291721405e2ed769b5b0bdc90eb1f78a9a01c665a7747c1ca7ad76f66ac2d","src/argon2.rs":"df5dfa100a25abf57be38ba22dc201a0b9f75dd9d6b3a098151382b0cda5d874","src/block.rs":"20c0198d37eab2a096c78e0c38b4b8bcc2eeba3256e6a57dce8f732be0bc1920","src/common.rs":"a24dbea8091d8439279713c27b434c732f5c4c06482b51876fd5d8e0631c18a0","src/config.rs":"c3dbd2d15e55cb47dc16cbb17ba2bfba4eff33de7d7f8bb50511184edc255754","src/context.rs":"d652c26c90a4499ddc4460861486e14b95a90eefc0124ee0c9f1e3440c37ad8a","src/core.rs":"962d64f6d1b1c8f4217af5cd516874260aa080645dd951628a9c0979722347aa","src/decoded.rs":"3ccdac14ceff9c7c3596cac8a0725588bf6dfb728b64c9b9cda5b88aa18d2238","src/encoding.rs":"5579d6bc5c81e7baacfa510bed01938b4d4c2d13cfa697cb1b38baffd4c82704","src/error.rs":"72c862923c8e6f2bd54c02834dbdcc3b17337b8d0b5e8ff22b15e7c4c3c337a5","src/lib.rs":"11b123afab0e3ecdc6bd4c74dd2b6fccdd331ece49b5b94aee3fe81841b650a9","src/memory.rs":"25e7f5e6d349d14a76d7a457d9d4a28e6d583499e9612928843b3ebc3d257d35","src/result.rs":"92cb6463af8230655bf946ff5e52d92c26674fbf47e0640bdbc631a4400cd644","src/thread_mode.rs":"afeb39243e1bb253b124732b36c46ffd8249a4996d5d043106b34679144a1523","src/variant.rs":"e1d88e1dfb1a2ab01bf59b8699ef7548b1d7c40426baaef46ae955e9ff696cb8","src/version.rs":"91d493f1331dd2cba71b4e6a426ecb5de42a52a26c6e3659083a322b3c14c293","tests/integration_test.rs":"97bc547a9b0d38623a593928f5785166e87d9bdf1c8105a00b006644e06b9faa"},"package":"4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf"} \ No newline at end of file
diff --git a/third_party/rust/rust-argon2/CHANGELOG.md b/third_party/rust/rust-argon2/CHANGELOG.md
new file mode 100644
index 0000000000..3619b27eaf
--- /dev/null
+++ b/third_party/rust/rust-argon2/CHANGELOG.md
@@ -0,0 +1,44 @@
+ChangeLog for rust-argon2
+=========================
+
+This documents all notable changes to
+[rust-argon2](https://github.com/sru-systems/rust-argon2).
+
+## 0.5.1
+
+- Use crossbeam utils 0.6 instead of crossbeam 0.5
+
+
+## 0.5.0
+
+- Replace blake2-rfc with blake2b_simd.
+
+
+## 0.4.0
+
+- Replace rustc-serialize dependency with base64 and hex.
+- Update base64 dependency.
+- Update crossbeam dependency.
+- Update hex dependency.
+- Allow updating to minor versions of blake2-rfc.
+
+
+## 0.3.0
+
+- Embed Config struct in Context struct.
+
+
+## 0.2.0
+
+- Use ThreadMode enum instead of explicit thread number.
+- Use a Config struct instead of explicit configuration arguments.
+- Use references instead of vectors for byte data in the Context struct.
+- Deprecate the following functions:
+ - hash_encoded_defaults
+ - hash_encoded_old
+ - hash_encoded_std
+ - hash_raw_defaults
+ - hash_raw_old
+ - hash_raw_std
+ - verify_raw_old
+ - verify_raw_std
diff --git a/third_party/rust/rust-argon2/Cargo.toml b/third_party/rust/rust-argon2/Cargo.toml
new file mode 100644
index 0000000000..65e3547997
--- /dev/null
+++ b/third_party/rust/rust-argon2/Cargo.toml
@@ -0,0 +1,36 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "rust-argon2"
+version = "0.5.1"
+authors = ["Martijn Rijkeboer <mrr@sru-systems.com>"]
+description = "Rust implementation of the Argon2 password hashing function."
+homepage = "https://github.com/sru-systems/rust-argon2"
+documentation = "https://docs.sru-systems.com/rust-argon2/0.5.0/argon2/"
+readme = "README.md"
+keywords = ["argon2", "argon2d", "argon2i", "hash", "password"]
+license = "MIT/Apache-2.0"
+repository = "https://github.com/sru-systems/rust-argon2"
+
+[lib]
+name = "argon2"
+[dependencies.base64]
+version = "0.10"
+
+[dependencies.blake2b_simd]
+version = "0.5"
+
+[dependencies.crossbeam-utils]
+version = "0.6"
+[dev-dependencies.hex]
+version = "0.3"
diff --git a/third_party/rust/rust-argon2/LICENSE-APACHE b/third_party/rust/rust-argon2/LICENSE-APACHE
new file mode 100644
index 0000000000..16fe87b06e
--- /dev/null
+++ b/third_party/rust/rust-argon2/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/third_party/rust/rust-argon2/LICENSE-MIT b/third_party/rust/rust-argon2/LICENSE-MIT
new file mode 100644
index 0000000000..96cd88f451
--- /dev/null
+++ b/third_party/rust/rust-argon2/LICENSE-MIT
@@ -0,0 +1,22 @@
+The MIT license.
+
+Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/rust-argon2/README.md b/third_party/rust/rust-argon2/README.md
new file mode 100644
index 0000000000..b1280af6c2
--- /dev/null
+++ b/third_party/rust/rust-argon2/README.md
@@ -0,0 +1,85 @@
+# Rust-argon2
+
+Rust library for hashing passwords using
+[Argon2](https://github.com/P-H-C/phc-winner-argon2), the password-hashing
+function that won the
+[Password Hashing Competition (PHC)](https://password-hashing.net).
+
+## Usage
+
+To use `rust-argon2`, add the following to your Cargo.toml:
+
+```toml
+[dependencies]
+rust-argon2 = "0.5"
+```
+
+And the following to your crate root:
+
+```rust
+extern crate argon2;
+```
+
+
+## Examples
+
+Create a password hash using the defaults and verify it:
+
+```rust
+use argon2::{self, Config};
+
+let password = b"password";
+let salt = b"randomsalt";
+let config = Config::default();
+let hash = argon2::hash_encoded(password, salt, &config).unwrap();
+let matches = argon2::verify_encoded(&hash, password).unwrap();
+assert!(matches);
+```
+
+Create a password hash with custom settings and verify it:
+
+```rust
+use argon2::{self, Config, ThreadMode, Variant, Version};
+
+let password = b"password";
+let salt = b"othersalt";
+let config = Config {
+ variant: Variant::Argon2i,
+ version: Version::Version13,
+ mem_cost: 65536,
+ time_cost: 10,
+ lanes: 4,
+ thread_mode: ThreadMode::Parallel,
+ secret: &[],
+ ad: &[],
+ hash_length: 32
+};
+let hash = argon2::hash_encoded(password, salt, &config).unwrap();
+let matches = argon2::verify_encoded(&hash, password).unwrap();
+assert!(matches);
+```
+
+
+## Limitations
+
+This crate has the same limitation as the `blake2-rfc` crate that it uses.
+It does not attempt to clear potentially sensitive data from its work
+memory. To do so correctly without a heavy performance penalty would
+require help from the compiler. It's better to not attempt to do so than to
+present a false assurance.
+
+This version uses the standard implementation and does not yet implement
+optimizations. Therefore, it is not the fastest implementation available.
+
+
+## License
+
+Rust-argon2 is dual licensed under the [MIT](LICENSE-MIT) and
+[Apache 2.0](LICENSE-APACHE) licenses, the same licenses as the Rust compiler.
+
+
+## Contributions
+
+Contributions are welcome. By submitting a pull request you are agreeing to
+make you work available under the license terms of the Rust-argon2 project.
+
diff --git a/third_party/rust/rust-argon2/src/argon2.rs b/third_party/rust/rust-argon2/src/argon2.rs
new file mode 100644
index 0000000000..d16f3487a4
--- /dev/null
+++ b/third_party/rust/rust-argon2/src/argon2.rs
@@ -0,0 +1,717 @@
+// Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com>
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::context::Context;
+use super::config::Config;
+use super::core;
+use super::encoding;
+use super::memory::Memory;
+use super::result::Result;
+use super::thread_mode::ThreadMode;
+use super::variant::Variant;
+use super::version::Version;
+
+/// Returns the length of the encoded string.
+///
+/// # Remarks
+///
+/// The length is **one** less that the original C version, since no null
+/// terminator is used.
+///
+/// # Examples
+///
+/// ```rust
+/// use argon2::{self, Variant};
+///
+/// let variant = Variant::Argon2i;
+/// let mem = 4096;
+/// let time = 10;
+/// let parallelism = 10;
+/// let salt_len = 8;
+/// let hash_len = 32;
+/// let enc_len = argon2::encoded_len(variant, mem, time, parallelism, salt_len, hash_len);
+/// assert_eq!(enc_len, 86);
+/// ```
+#[cfg_attr(rustfmt, rustfmt_skip)]
+pub fn encoded_len(
+ variant: Variant,
+ mem_cost: u32,
+ time_cost: u32,
+ parallelism: u32,
+ salt_len: u32,
+ hash_len: u32
+) -> u32 {
+ ("$$v=$m=,t=,p=$$".len() as u32) +
+ (variant.as_lowercase_str().len() as u32) +
+ encoding::num_len(Version::default().as_u32()) +
+ encoding::num_len(mem_cost) +
+ encoding::num_len(time_cost) +
+ encoding::num_len(parallelism) +
+ encoding::base64_len(salt_len) +
+ encoding::base64_len(hash_len)
+}
+
+/// Hashes the password and returns the encoded hash.
+///
+/// # Examples
+///
+/// Create an encoded hash with the default configuration:
+///
+/// ```
+/// use argon2::{self, Config};
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let config = Config::default();
+/// let encoded = argon2::hash_encoded(pwd, salt, &config).unwrap();
+/// ```
+///
+///
+/// Create an Argon2d encoded hash with 4 lanes and parallel execution:
+///
+/// ```
+/// use argon2::{self, Config, ThreadMode, Variant};
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let mut config = Config::default();
+/// config.variant = Variant::Argon2d;
+/// config.lanes = 4;
+/// config.thread_mode = ThreadMode::Parallel;
+/// let encoded = argon2::hash_encoded(pwd, salt, &config).unwrap();
+/// ```
+pub fn hash_encoded(pwd: &[u8], salt: &[u8], config: &Config) -> Result<String> {
+ let context = Context::new(config.clone(), pwd, salt)?;
+ let hash = run(&context);
+ let encoded = encoding::encode_string(&context, &hash);
+ Ok(encoded)
+}
+
+/// Hashes the password using default settings and returns the encoded hash.
+///
+/// # Examples
+///
+/// ```
+/// use argon2;
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let encoded = argon2::hash_encoded_defaults(pwd, salt).unwrap();
+/// ```
+///
+/// The above rewritten using `hash_encoded`:
+///
+/// ```
+/// use argon2::{self, Config};
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let config = Config::default();
+/// let encoded = argon2::hash_encoded(pwd, salt, &config).unwrap();
+/// ```
+#[deprecated(since = "0.2.0", note = "please use `hash_encoded` instead")]
+pub fn hash_encoded_defaults(pwd: &[u8], salt: &[u8]) -> Result<String> {
+ hash_encoded(pwd, salt, &Config::default())
+}
+
+/// Hashes the password and returns the encoded hash (pre 0.2.0 `hash_encoded`).
+///
+/// # Examples
+///
+///
+/// ```
+/// use argon2::{self, Variant, Version};
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let mem_cost = 4096;
+/// let time_cost = 10;
+/// let lanes = 1;
+/// let threads = 1;
+/// let secret = b"secret value";
+/// let ad = b"associated data";
+/// let hash_len = 32;
+/// let encoded = argon2::hash_encoded_old(Variant::Argon2i,
+/// Version::Version13,
+/// mem_cost,
+/// time_cost,
+/// lanes,
+/// threads,
+/// pwd,
+/// salt,
+/// secret,
+/// ad,
+/// hash_len).unwrap();
+/// ```
+///
+/// The above rewritten using the new `hash_encoded`:
+///
+/// ```
+/// use argon2::{self, Config, ThreadMode, Variant, Version};
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let config = Config {
+/// variant: Variant::Argon2i,
+/// version: Version::Version13,
+/// mem_cost: 4096,
+/// time_cost: 10,
+/// lanes: 1,
+/// thread_mode: ThreadMode::Sequential,
+/// secret: b"secret value",
+/// ad: b"associated data",
+/// hash_length: 32,
+/// };
+/// let encoded = argon2::hash_encoded(pwd, salt, &config).unwrap();
+/// ```
+#[deprecated(since = "0.2.0", note = "please use new `hash_encoded` instead")]
+pub fn hash_encoded_old(
+ variant: Variant,
+ version: Version,
+ mem_cost: u32,
+ time_cost: u32,
+ lanes: u32,
+ threads: u32,
+ pwd: &[u8],
+ salt: &[u8],
+ secret: &[u8],
+ ad: &[u8],
+ hash_len: u32,
+) -> Result<String> {
+ let config = Config {
+ variant: variant,
+ version: version,
+ mem_cost: mem_cost,
+ time_cost: time_cost,
+ lanes: lanes,
+ thread_mode: ThreadMode::from_threads(threads),
+ secret: secret,
+ ad: ad,
+ hash_length: hash_len,
+ };
+ hash_encoded(pwd, salt, &config)
+}
+
+/// Hashes the password and returns the encoded hash (standard).
+///
+/// # Examples
+///
+///
+/// ```
+/// use argon2::{self, Variant, Version};
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let mem_cost = 4096;
+/// let time_cost = 10;
+/// let parallelism = 1;
+/// let hash_len = 32;
+/// let encoded = argon2::hash_encoded_std(Variant::Argon2i,
+/// Version::Version13,
+/// mem_cost,
+/// time_cost,
+/// parallelism,
+/// pwd,
+/// salt,
+/// hash_len).unwrap();
+/// ```
+///
+/// The above rewritten using `hash_encoded`:
+///
+/// ```
+/// use argon2::{self, Config, ThreadMode, Variant, Version};
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let config = Config {
+/// variant: Variant::Argon2i,
+/// version: Version::Version13,
+/// mem_cost: 4096,
+/// time_cost: 10,
+/// lanes: 1,
+/// thread_mode: ThreadMode::Sequential,
+/// secret: &[],
+/// ad: &[],
+/// hash_length: 32,
+/// };
+/// let encoded = argon2::hash_encoded(pwd, salt, &config).unwrap();
+/// ```
+#[deprecated(since = "0.2.0", note = "please use `hash_encoded` instead")]
+pub fn hash_encoded_std(
+ variant: Variant,
+ version: Version,
+ mem_cost: u32,
+ time_cost: u32,
+ parallelism: u32,
+ pwd: &[u8],
+ salt: &[u8],
+ hash_len: u32,
+) -> Result<String> {
+ let config = Config {
+ variant: variant,
+ version: version,
+ mem_cost: mem_cost,
+ time_cost: time_cost,
+ lanes: parallelism,
+ thread_mode: ThreadMode::from_threads(parallelism),
+ secret: &[],
+ ad: &[],
+ hash_length: hash_len,
+ };
+ hash_encoded(pwd, salt, &config)
+}
+
+/// Hashes the password and returns the hash as a vector.
+///
+/// # Examples
+///
+/// Create a hash with the default configuration:
+///
+/// ```
+/// use argon2::{self, Config};
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let config = Config::default();
+/// let vec = argon2::hash_raw(pwd, salt, &config).unwrap();
+/// ```
+///
+///
+/// Create an Argon2d hash with 4 lanes and parallel execution:
+///
+/// ```
+/// use argon2::{self, Config, ThreadMode, Variant};
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let mut config = Config::default();
+/// config.variant = Variant::Argon2d;
+/// config.lanes = 4;
+/// config.thread_mode = ThreadMode::Parallel;
+/// let vec = argon2::hash_raw(pwd, salt, &config).unwrap();
+/// ```
+pub fn hash_raw(pwd: &[u8], salt: &[u8], config: &Config) -> Result<Vec<u8>> {
+ let context = Context::new(config.clone(), pwd, salt)?;
+ let hash = run(&context);
+ Ok(hash)
+}
+
+/// Hashes the password using default settings and returns the hash as a vector.
+///
+/// # Examples
+///
+/// ```
+/// use argon2;
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let vec = argon2::hash_raw_defaults(pwd, salt).unwrap();
+/// ```
+///
+/// The above rewritten using `hash_raw`:
+///
+/// ```
+/// use argon2::{self, Config};
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let config = Config::default();
+/// let vec = argon2::hash_raw(pwd, salt, &config).unwrap();
+/// ```
+#[deprecated(since = "0.2.0", note = "please use `hash_raw` instead")]
+pub fn hash_raw_defaults(pwd: &[u8], salt: &[u8]) -> Result<Vec<u8>> {
+ hash_raw(pwd, salt, &Config::default())
+}
+
+/// Hashes the password and returns the hash as a vector (pre 0.2.0 `hash_raw`).
+///
+/// # Examples
+///
+///
+/// ```
+/// use argon2::{self, Variant, Version};
+///
+/// let mem_cost = 4096;
+/// let time_cost = 10;
+/// let lanes = 1;
+/// let threads = 1;
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let secret = b"secret value";
+/// let ad = b"associated data";
+/// let hash_len = 32;
+/// let vec = argon2::hash_raw_old(Variant::Argon2i,
+/// Version::Version13,
+/// mem_cost,
+/// time_cost,
+/// lanes,
+/// threads,
+/// pwd,
+/// salt,
+/// secret,
+/// ad,
+/// hash_len).unwrap();
+/// ```
+///
+/// The above rewritten using the new `hash_raw`:
+///
+/// ```
+/// use argon2::{self, Config, ThreadMode, Variant, Version};
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let config = Config {
+/// variant: Variant::Argon2i,
+/// version: Version::Version13,
+/// mem_cost: 4096,
+/// time_cost: 10,
+/// lanes: 1,
+/// thread_mode: ThreadMode::Sequential,
+/// secret: b"secret value",
+/// ad: b"associated data",
+/// hash_length: 32,
+/// };
+/// let vec = argon2::hash_raw(pwd, salt, &config);
+/// ```
+#[deprecated(since = "0.2.0", note = "please use new `hash_raw` instead")]
+pub fn hash_raw_old(
+ variant: Variant,
+ version: Version,
+ mem_cost: u32,
+ time_cost: u32,
+ lanes: u32,
+ threads: u32,
+ pwd: &[u8],
+ salt: &[u8],
+ secret: &[u8],
+ ad: &[u8],
+ hash_len: u32,
+) -> Result<Vec<u8>> {
+ let config = Config {
+ variant: variant,
+ version: version,
+ mem_cost: mem_cost,
+ time_cost: time_cost,
+ lanes: lanes,
+ thread_mode: ThreadMode::from_threads(threads),
+ secret: secret,
+ ad: ad,
+ hash_length: hash_len,
+ };
+ hash_raw(pwd, salt, &config)
+}
+
+/// Hashes the password and returns the hash as a vector (standard).
+///
+/// # Examples
+///
+///
+/// ```
+/// use argon2::{self, Variant, Version};
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let mem_cost = 4096;
+/// let time_cost = 10;
+/// let parallelism = 1;
+/// let hash_len = 32;
+/// let vec = argon2::hash_raw_std(Variant::Argon2i,
+/// Version::Version13,
+/// mem_cost,
+/// time_cost,
+/// parallelism,
+/// pwd,
+/// salt,
+/// hash_len).unwrap();
+/// ```
+///
+/// The above rewritten using `hash_raw`:
+///
+/// ```
+/// use argon2::{self, Config, ThreadMode, Variant, Version};
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let config = Config {
+/// variant: Variant::Argon2i,
+/// version: Version::Version13,
+/// mem_cost: 4096,
+/// time_cost: 10,
+/// lanes: 1,
+/// thread_mode: ThreadMode::Sequential,
+/// secret: &[],
+/// ad: &[],
+/// hash_length: 32,
+/// };
+/// let vec = argon2::hash_raw(pwd, salt, &config);
+/// ```
+#[deprecated(since = "0.2.0", note = "please use `hash_raw` instead")]
+pub fn hash_raw_std(
+ variant: Variant,
+ version: Version,
+ mem_cost: u32,
+ time_cost: u32,
+ parallelism: u32,
+ pwd: &[u8],
+ salt: &[u8],
+ hash_len: u32,
+) -> Result<Vec<u8>> {
+ let config = Config {
+ variant: variant,
+ version: version,
+ mem_cost: mem_cost,
+ time_cost: time_cost,
+ lanes: parallelism,
+ thread_mode: ThreadMode::from_threads(parallelism),
+ secret: &[],
+ ad: &[],
+ hash_length: hash_len,
+ };
+ hash_raw(pwd, salt, &config)
+}
+
+/// Verifies the password with the encoded hash.
+///
+/// # Examples
+///
+/// ```
+/// use argon2;
+///
+/// let enc = "$argon2i$v=19$m=4096,t=3,p=1$c29tZXNhbHQ\
+/// $iWh06vD8Fy27wf9npn6FXWiCX4K6pW6Ue1Bnzz07Z8A";
+/// let pwd = b"password";
+/// let res = argon2::verify_encoded(enc, pwd).unwrap();
+/// assert!(res);
+/// ```
+pub fn verify_encoded(encoded: &str, pwd: &[u8]) -> Result<bool> {
+ verify_encoded_ext(encoded, pwd, &[], &[])
+}
+
+/// Verifies the password with the encoded hash, secret and associated data.
+///
+/// # Examples
+///
+/// ```
+/// use argon2;
+///
+/// let enc = "$argon2i$v=19$m=4096,t=3,p=1$c29tZXNhbHQ\
+/// $OlcSvlN20Lz43sK3jhCJ9K04oejhiY0AmI+ck6nuETo";
+/// let pwd = b"password";
+/// let secret = b"secret";
+/// let ad = b"ad";
+/// let res = argon2::verify_encoded_ext(enc, pwd, secret, ad).unwrap();
+/// assert!(res);
+/// ```
+pub fn verify_encoded_ext(encoded: &str, pwd: &[u8], secret: &[u8], ad: &[u8]) -> Result<bool> {
+ let decoded = encoding::decode_string(encoded)?;
+ let config = Config {
+ variant: decoded.variant,
+ version: decoded.version,
+ mem_cost: decoded.mem_cost,
+ time_cost: decoded.time_cost,
+ lanes: decoded.parallelism,
+ thread_mode: ThreadMode::from_threads(decoded.parallelism),
+ secret: secret,
+ ad: ad,
+ hash_length: decoded.hash.len() as u32,
+ };
+ verify_raw(pwd, &decoded.salt, &decoded.hash, &config)
+}
+
+/// Verifies the password with the supplied configuration.
+///
+/// # Examples
+///
+///
+/// ```
+/// use argon2::{self, Config};
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let hash = &[137, 104, 116, 234, 240, 252, 23, 45, 187, 193, 255, 103, 166,
+/// 126, 133, 93, 104, 130, 95, 130, 186, 165, 110, 148, 123, 80,
+/// 103, 207, 61, 59, 103, 192];
+/// let config = Config::default();
+/// let res = argon2::verify_raw(pwd, salt, hash, &config).unwrap();
+/// assert!(res);
+/// ```
+pub fn verify_raw(pwd: &[u8], salt: &[u8], hash: &[u8], config: &Config) -> Result<bool> {
+ let config = Config {
+ hash_length: hash.len() as u32,
+ ..config.clone()
+ };
+ let context = Context::new(config, pwd, salt)?;
+ Ok(run(&context) == hash)
+}
+
+/// Verifies the password with the supplied settings (pre 0.2.0 `verify_raw`).
+///
+/// # Examples
+///
+/// ```
+/// use argon2::{self, Variant, Version};
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let hash = &[137, 104, 116, 234, 240, 252, 23, 45, 187, 193, 255, 103, 166,
+/// 126, 133, 93, 104, 130, 95, 130, 186, 165, 110, 148, 123, 80,
+/// 103, 207, 61, 59, 103, 192];
+/// let mem_cost = 4096;
+/// let time_cost = 3;
+/// let lanes = 1;
+/// let threads = 1;
+/// let secret = &[];
+/// let ad = &[];
+/// let res = argon2::verify_raw_old(Variant::Argon2i,
+/// Version::Version13,
+/// mem_cost,
+/// time_cost,
+/// lanes,
+/// threads,
+/// pwd,
+/// salt,
+/// secret,
+/// ad,
+/// hash).unwrap();
+/// assert!(res);
+/// ```
+///
+/// The above rewritten using the new `verify_raw`:
+///
+/// ```
+/// use argon2::{self, Config, ThreadMode, Variant, Version};
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let hash = &[137, 104, 116, 234, 240, 252, 23, 45, 187, 193, 255, 103, 166,
+/// 126, 133, 93, 104, 130, 95, 130, 186, 165, 110, 148, 123, 80,
+/// 103, 207, 61, 59, 103, 192];
+/// let config = Config {
+/// variant: Variant::Argon2i,
+/// version: Version::Version13,
+/// mem_cost: 4096,
+/// time_cost: 3,
+/// lanes: 1,
+/// thread_mode: ThreadMode::Sequential,
+/// secret: &[],
+/// ad: &[],
+/// hash_length: hash.len() as u32,
+/// };
+/// let res = argon2::verify_raw(pwd, salt, hash, &config).unwrap();
+/// assert!(res);
+/// ```
+#[deprecated(since = "0.2.0", note = "please use new `verify_raw` instead")]
+pub fn verify_raw_old(
+ variant: Variant,
+ version: Version,
+ mem_cost: u32,
+ time_cost: u32,
+ lanes: u32,
+ threads: u32,
+ pwd: &[u8],
+ salt: &[u8],
+ secret: &[u8],
+ ad: &[u8],
+ hash: &[u8],
+) -> Result<bool> {
+ let config = Config {
+ variant: variant,
+ version: version,
+ mem_cost: mem_cost,
+ time_cost: time_cost,
+ lanes: lanes,
+ thread_mode: ThreadMode::from_threads(threads),
+ secret: secret,
+ ad: ad,
+ hash_length: hash.len() as u32,
+ };
+ verify_raw(pwd, salt, hash, &config)
+}
+
+/// Verifies the password with the supplied settings (standard).
+///
+/// # Examples
+///
+///
+/// ```
+/// use argon2::{self, Variant, Version};
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let hash = &[137, 104, 116, 234, 240, 252, 23, 45, 187, 193, 255, 103, 166,
+/// 126, 133, 93, 104, 130, 95, 130, 186, 165, 110, 148, 123, 80,
+/// 103, 207, 61, 59, 103, 192];
+/// let mem_cost = 4096;
+/// let time_cost = 3;
+/// let parallelism = 1;
+/// let res = argon2::verify_raw_std(Variant::Argon2i,
+/// Version::Version13,
+/// mem_cost,
+/// time_cost,
+/// parallelism,
+/// pwd,
+/// salt,
+/// hash).unwrap();
+/// assert!(res);
+/// ```
+///
+/// The above rewritten using `verify_raw`:
+///
+/// ```
+/// use argon2::{self, Config, ThreadMode, Variant, Version};
+///
+/// let pwd = b"password";
+/// let salt = b"somesalt";
+/// let hash = &[137, 104, 116, 234, 240, 252, 23, 45, 187, 193, 255, 103, 166,
+/// 126, 133, 93, 104, 130, 95, 130, 186, 165, 110, 148, 123, 80,
+/// 103, 207, 61, 59, 103, 192];
+/// let config = Config {
+/// variant: Variant::Argon2i,
+/// version: Version::Version13,
+/// mem_cost: 4096,
+/// time_cost: 3,
+/// lanes: 1,
+/// thread_mode: ThreadMode::Sequential,
+/// secret: &[],
+/// ad: &[],
+/// hash_length: hash.len() as u32,
+/// };
+/// let res = argon2::verify_raw(pwd, salt, hash, &config).unwrap();
+/// assert!(res);
+/// ```
+#[deprecated(since = "0.2.0", note = "please use `verify_raw` instead")]
+pub fn verify_raw_std(
+ variant: Variant,
+ version: Version,
+ mem_cost: u32,
+ time_cost: u32,
+ parallelism: u32,
+ pwd: &[u8],
+ salt: &[u8],
+ hash: &[u8],
+) -> Result<bool> {
+ let config = Config {
+ variant: variant,
+ version: version,
+ mem_cost: mem_cost,
+ time_cost: time_cost,
+ lanes: parallelism,
+ thread_mode: ThreadMode::from_threads(parallelism),
+ secret: &[],
+ ad: &[],
+ hash_length: hash.len() as u32,
+ };
+ verify_raw(pwd, salt, hash, &config)
+}
+
+fn run(context: &Context) -> Vec<u8> {
+ let mut memory = Memory::new(context.config.lanes, context.lane_length);
+ core::initialize(context, &mut memory);
+ core::fill_memory_blocks(context, &mut memory);
+ core::finalize(context, &memory)
+}
diff --git a/third_party/rust/rust-argon2/src/block.rs b/third_party/rust/rust-argon2/src/block.rs
new file mode 100644
index 0000000000..134bb4b66f
--- /dev/null
+++ b/third_party/rust/rust-argon2/src/block.rs
@@ -0,0 +1,142 @@
+// Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com>
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::{fmt, mem};
+use std::fmt::Debug;
+use std::ops::{BitXorAssign, Index, IndexMut};
+use super::common;
+
+/// Structure for the (1KB) memory block implemented as 128 64-bit words.
+pub struct Block([u64; common::QWORDS_IN_BLOCK]);
+
+impl Block {
+ /// Gets the byte slice representation of the block.
+ pub fn as_u8(&self) -> &[u8] {
+ let bytes: &[u8; common::BLOCK_SIZE] = unsafe { mem::transmute(&self.0) };
+ bytes
+ }
+
+ /// Gets the mutable byte slice representation of the block.
+ pub fn as_u8_mut(&mut self) -> &mut [u8] {
+ let bytes: &mut [u8; common::BLOCK_SIZE] = unsafe { mem::transmute(&mut self.0) };
+ bytes
+ }
+
+ /// Copies self to destination.
+ pub fn copy_to(&self, dst: &mut Block) {
+ for (d, s) in dst.0.iter_mut().zip(self.0.iter()) {
+ *d = *s
+ }
+ }
+
+ /// Creates a new block filled with zeros.
+ pub fn zero() -> Block {
+ Block([0u64; common::QWORDS_IN_BLOCK])
+ }
+}
+
+impl<'a> BitXorAssign<&'a Block> for Block {
+ fn bitxor_assign(&mut self, rhs: &Block) {
+ for (s, r) in self.0.iter_mut().zip(rhs.0.iter()) {
+ *s ^= *r
+ }
+ }
+}
+
+impl Clone for Block {
+ fn clone(&self) -> Block {
+ Block(self.0)
+ }
+}
+
+impl Debug for Block {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.debug_list().entries(self.0.iter()).finish()
+ }
+}
+
+impl Eq for Block {}
+
+impl Index<usize> for Block {
+ type Output = u64;
+ fn index(&self, index: usize) -> &u64 {
+ &self.0[index]
+ }
+}
+
+impl IndexMut<usize> for Block {
+ fn index_mut(&mut self, index: usize) -> &mut u64 {
+ &mut self.0[index]
+ }
+}
+
+impl PartialEq for Block {
+ fn eq(&self, other: &Block) -> bool {
+ let mut equal = true;
+ for (s, o) in self.0.iter().zip(other.0.iter()) {
+ if s != o {
+ equal = false;
+ }
+ }
+ equal
+ }
+}
+
+
+#[cfg(test)]
+mod tests {
+
+ use common;
+ use super::*;
+
+ #[test]
+ fn as_u8_returns_correct_slice() {
+ let block = Block::zero();
+ let expected = vec![0u8; 1024];
+ let actual = block.as_u8();
+ assert_eq!(actual, expected.as_slice());
+ }
+
+ #[test]
+ fn as_u8_mut_returns_correct_slice() {
+ let mut block = Block::zero();
+ let mut expected = vec![0u8; 1024];
+ let actual = block.as_u8_mut();
+ assert_eq!(actual, expected.as_mut_slice());
+ }
+
+ #[test]
+ fn bitxor_assign_updates_lhs() {
+ let mut lhs = Block([0u64; common::QWORDS_IN_BLOCK]);
+ let rhs = Block([1u64; common::QWORDS_IN_BLOCK]);
+ lhs ^= &rhs;
+ assert_eq!(lhs, rhs);
+ }
+
+ #[test]
+ fn copy_to_copies_block() {
+ let src = Block([1u64; common::QWORDS_IN_BLOCK]);
+ let mut dst = Block([0u64; common::QWORDS_IN_BLOCK]);
+ src.copy_to(&mut dst);
+ assert_eq!(dst, src);
+ }
+
+ #[test]
+ fn clone_clones_block() {
+ let orig = Block([1u64; common::QWORDS_IN_BLOCK]);
+ let copy = orig.clone();
+ assert_eq!(copy, orig);
+ }
+
+ #[test]
+ fn zero_creates_block_will_all_zeros() {
+ let expected = Block([0u64; common::QWORDS_IN_BLOCK]);
+ let actual = Block::zero();
+ assert_eq!(actual, expected);
+ }
+}
diff --git a/third_party/rust/rust-argon2/src/common.rs b/third_party/rust/rust-argon2/src/common.rs
new file mode 100644
index 0000000000..dffcac7916
--- /dev/null
+++ b/third_party/rust/rust-argon2/src/common.rs
@@ -0,0 +1,92 @@
+// Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com>
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// Default number of lanes (degree of parallelism).
+pub const DEF_LANES: u32 = 1;
+
+/// Minimum number of lanes (degree of parallelism).
+pub const MIN_LANES: u32 = 1;
+
+/// Maximum number of lanes (degree of parallelism).
+pub const MAX_LANES: u32 = 0x00FFFFFF;
+
+/// Number of synchronization points between lanes per pass.
+pub const SYNC_POINTS: u32 = 4;
+
+/// Default digest size in bytes.
+pub const DEF_HASH_LENGTH: u32 = 32;
+
+/// Minimum digest size in bytes.
+pub const MIN_HASH_LENGTH: u32 = 4;
+
+/// Maximum digest size in bytes.
+pub const MAX_HASH_LENGTH: u32 = 0xFFFFFFFF;
+
+/// Default number of memory blocks (2^12).
+pub const DEF_MEMORY: u32 = 4096;
+
+/// Minimum number of memory blocks (each of BLOCK_SIZE bytes).
+pub const MIN_MEMORY: u32 = 2 * SYNC_POINTS;
+
+/// Maximum number of memory blocks (each of BLOCK_SIZE bytes).
+#[cfg(target_pointer_width = "32")]
+pub const MAX_MEMORY: u32 = 0x200000;
+#[cfg(target_pointer_width = "64")]
+pub const MAX_MEMORY: u32 = 0xFFFFFFFF;
+
+/// Default number of passes.
+pub const DEF_TIME: u32 = 3;
+
+/// Minimum number of passes
+pub const MIN_TIME: u32 = 1;
+
+/// Maximum number of passes.
+pub const MAX_TIME: u32 = 0xFFFFFFFF;
+
+/// Minimum password length in bytes.
+pub const MIN_PWD_LENGTH: u32 = 0;
+
+/// Maximum password length in bytes.
+pub const MAX_PWD_LENGTH: u32 = 0xFFFFFFFF;
+
+/// Minimum associated data length in bytes.
+pub const MIN_AD_LENGTH: u32 = 0;
+
+/// Maximum associated data length in bytes.
+pub const MAX_AD_LENGTH: u32 = 0xFFFFFFFF;
+
+/// Minimum salt length in bytes.
+pub const MIN_SALT_LENGTH: u32 = 8;
+
+/// Maximum salt length in bytes.
+pub const MAX_SALT_LENGTH: u32 = 0xFFFFFFFF;
+
+/// Minimum key length in bytes.
+pub const MIN_SECRET_LENGTH: u32 = 0;
+
+/// Maximum key length in bytes.
+pub const MAX_SECRET_LENGTH: u32 = 0xFFFFFFFF;
+
+/// Memory block size in bytes.
+pub const BLOCK_SIZE: usize = 1024;
+
+/// Number of quad words in a block.
+pub const QWORDS_IN_BLOCK: usize = BLOCK_SIZE / 8;
+
+/// Number of pseudo-random values generated by one call to Blake in Argon2i
+/// to generate reference block positions.
+pub const ADDRESSES_IN_BLOCK: u32 = 128;
+
+/// Pre-hashing digest length.
+pub const PREHASH_DIGEST_LENGTH: usize = 64;
+
+/// Pre-hashing digest length with extension.
+pub const PREHASH_SEED_LENGTH: usize = 72;
+
+/// Blake2b output length in bytes.
+pub const BLAKE2B_OUT_LENGTH: usize = 64;
diff --git a/third_party/rust/rust-argon2/src/config.rs b/third_party/rust/rust-argon2/src/config.rs
new file mode 100644
index 0000000000..c63cecc43a
--- /dev/null
+++ b/third_party/rust/rust-argon2/src/config.rs
@@ -0,0 +1,105 @@
+// Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com>
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::common;
+use super::thread_mode::ThreadMode;
+use super::variant::Variant;
+use super::version::Version;
+
+/// Structure containing configuration settings.
+///
+/// # Examples
+///
+/// ```
+/// use argon2::{Config, ThreadMode, Variant, Version};
+///
+/// let config = Config::default();
+/// assert_eq!(config.ad, &[]);
+/// assert_eq!(config.hash_length, 32);
+/// assert_eq!(config.lanes, 1);
+/// assert_eq!(config.mem_cost, 4096);
+/// assert_eq!(config.secret, &[]);
+/// assert_eq!(config.thread_mode, ThreadMode::Sequential);
+/// assert_eq!(config.time_cost, 3);
+/// assert_eq!(config.variant, Variant::Argon2i);
+/// assert_eq!(config.version, Version::Version13);
+/// ```
+#[derive(Clone, Debug, PartialEq)]
+pub struct Config<'a> {
+ /// The associated data.
+ pub ad: &'a [u8],
+
+ /// The length of the resulting hash.
+ pub hash_length: u32,
+
+ /// The number of lanes.
+ pub lanes: u32,
+
+ /// The amount of memory requested (KB).
+ pub mem_cost: u32,
+
+ /// The key.
+ pub secret: &'a [u8],
+
+ /// The thread mode.
+ pub thread_mode: ThreadMode,
+
+ /// The number of passes.
+ pub time_cost: u32,
+
+ /// The variant.
+ pub variant: Variant,
+
+ /// The version number.
+ pub version: Version,
+}
+
+impl<'a> Config<'a> {
+ pub fn uses_sequential(&self) -> bool {
+ self.thread_mode == ThreadMode::Sequential || self.lanes == 1
+ }
+}
+
+impl<'a> Default for Config<'a> {
+ fn default() -> Config<'a> {
+ Config {
+ ad: &[],
+ hash_length: common::DEF_HASH_LENGTH,
+ lanes: common::DEF_LANES,
+ mem_cost: common::DEF_MEMORY,
+ secret: &[],
+ thread_mode: ThreadMode::default(),
+ time_cost: common::DEF_TIME,
+ variant: Variant::default(),
+ version: Version::default(),
+ }
+ }
+}
+
+
+#[cfg(test)]
+mod tests {
+
+ use super::*;
+ use variant::Variant;
+ use version::Version;
+
+ #[test]
+ fn default_returns_correct_instance() {
+ let config = Config::default();
+ assert_eq!(config.ad, &[]);
+ assert_eq!(config.hash_length, 32);
+ assert_eq!(config.lanes, 1);
+ assert_eq!(config.mem_cost, 4096);
+ assert_eq!(config.secret, &[]);
+ assert_eq!(config.thread_mode, ThreadMode::Sequential);
+ assert_eq!(config.time_cost, 3);
+ assert_eq!(config.variant, Variant::Argon2i);
+ assert_eq!(config.version, Version::Version13);
+ }
+}
diff --git a/third_party/rust/rust-argon2/src/context.rs b/third_party/rust/rust-argon2/src/context.rs
new file mode 100644
index 0000000000..34eb076d1e
--- /dev/null
+++ b/third_party/rust/rust-argon2/src/context.rs
@@ -0,0 +1,213 @@
+// Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com>
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::common;
+use super::config::Config;
+use super::error::Error;
+use super::result::Result;
+
+/// Structure containing settings for the Argon2 algorithm. A combination of
+/// the original argon2_context and argon2_instance_t.
+#[derive(Debug, PartialEq)]
+pub struct Context<'a> {
+ /// The config for this context.
+ pub config: Config<'a>,
+
+ /// The length of a lane.
+ pub lane_length: u32,
+
+ /// The number of memory blocks.
+ pub memory_blocks: u32,
+
+ /// The password.
+ pub pwd: &'a [u8],
+
+ /// The salt.
+ pub salt: &'a [u8],
+
+ /// The length of a segment.
+ pub segment_length: u32,
+}
+
+impl<'a> Context<'a> {
+ /// Attempts to create a new context.
+ pub fn new(config: Config<'a>, pwd: &'a [u8], salt: &'a [u8]) -> Result<Context<'a>> {
+ if config.lanes < common::MIN_LANES {
+ return Err(Error::LanesTooFew);
+ } else if config.lanes > common::MAX_LANES {
+ return Err(Error::LanesTooMany);
+ }
+
+ let lanes = config.lanes;
+ if config.mem_cost < common::MIN_MEMORY {
+ return Err(Error::MemoryTooLittle);
+ } else if config.mem_cost > common::MAX_MEMORY {
+ return Err(Error::MemoryTooMuch);
+ } else if config.mem_cost < 8 * lanes {
+ return Err(Error::MemoryTooLittle);
+ }
+
+ if config.time_cost < common::MIN_TIME {
+ return Err(Error::TimeTooSmall);
+ } else if config.time_cost > common::MAX_TIME {
+ return Err(Error::TimeTooLarge);
+ }
+
+ let pwd_len = pwd.len();
+ if pwd_len < common::MIN_PWD_LENGTH as usize {
+ return Err(Error::PwdTooShort);
+ } else if pwd_len > common::MAX_PWD_LENGTH as usize {
+ return Err(Error::PwdTooLong);
+ }
+
+ let salt_len = salt.len();
+ if salt_len < common::MIN_SALT_LENGTH as usize {
+ return Err(Error::SaltTooShort);
+ } else if salt_len > common::MAX_SALT_LENGTH as usize {
+ return Err(Error::SaltTooLong);
+ }
+
+ let secret_len = config.secret.len();
+ if secret_len < common::MIN_SECRET_LENGTH as usize {
+ return Err(Error::SecretTooShort);
+ } else if secret_len > common::MAX_SECRET_LENGTH as usize {
+ return Err(Error::SecretTooLong);
+ }
+
+ let ad_len = config.ad.len();
+ if ad_len < common::MIN_AD_LENGTH as usize {
+ return Err(Error::AdTooShort);
+ } else if ad_len > common::MAX_AD_LENGTH as usize {
+ return Err(Error::AdTooLong);
+ }
+
+ if config.hash_length < common::MIN_HASH_LENGTH {
+ return Err(Error::OutputTooShort);
+ } else if config.hash_length > common::MAX_HASH_LENGTH {
+ return Err(Error::OutputTooLong);
+ }
+
+ let mut memory_blocks = config.mem_cost;
+ if memory_blocks < 2 * common::SYNC_POINTS * lanes {
+ memory_blocks = 2 * common::SYNC_POINTS * lanes;
+ }
+
+ let segment_length = memory_blocks / (lanes * common::SYNC_POINTS);
+ let memory_blocks = segment_length * (lanes * common::SYNC_POINTS);
+ let lane_length = segment_length * common::SYNC_POINTS;
+
+ Ok(Context {
+ config: config,
+ lane_length: lane_length,
+ memory_blocks: memory_blocks,
+ pwd: pwd,
+ salt: salt,
+ segment_length: segment_length,
+ })
+ }
+}
+
+
+#[cfg(test)]
+mod tests {
+
+ use error::Error;
+ use super::*;
+ use thread_mode::ThreadMode;
+ use variant::Variant;
+ use version::Version;
+
+ #[test]
+ fn new_returns_correct_instance() {
+ let config = Config {
+ ad: b"additionaldata",
+ hash_length: 32,
+ lanes: 4,
+ mem_cost: 4096,
+ secret: b"secret",
+ thread_mode: ThreadMode::Sequential,
+ time_cost: 3,
+ variant: Variant::Argon2i,
+ version: Version::Version13,
+ };
+ let pwd = b"password";
+ let salt = b"somesalt";
+ let result = Context::new(config.clone(), pwd, salt);
+ assert!(result.is_ok());
+
+ let context = result.unwrap();
+ assert_eq!(context.config, config);
+ assert_eq!(context.pwd, pwd);
+ assert_eq!(context.salt, salt);
+ assert_eq!(context.memory_blocks, 4096);
+ assert_eq!(context.segment_length, 256);
+ assert_eq!(context.lane_length, 1024);
+ }
+
+ #[test]
+ fn new_with_too_little_mem_cost_returns_correct_error() {
+ let config = Config {
+ mem_cost: 7,
+ ..Default::default()
+ };
+ assert_eq!(Context::new(config, &[0u8; 8], &[0u8; 8]), Err(Error::MemoryTooLittle));
+ }
+
+ #[test]
+ fn new_with_less_than_8_x_lanes_mem_cost_returns_correct_error() {
+ let config = Config {
+ lanes: 4,
+ mem_cost: 31,
+ ..Default::default()
+ };
+ assert_eq!(Context::new(config, &[0u8; 8], &[0u8; 8]), Err(Error::MemoryTooLittle));
+ }
+
+ #[test]
+ fn new_with_too_small_time_cost_returns_correct_error() {
+ let config = Config {
+ time_cost: 0,
+ ..Default::default()
+ };
+ assert_eq!(Context::new(config, &[0u8; 8], &[0u8; 8]), Err(Error::TimeTooSmall));
+ }
+
+ #[test]
+ fn new_with_too_few_lanes_returns_correct_error() {
+ let config = Config {
+ lanes: 0,
+ ..Default::default()
+ };
+ assert_eq!(Context::new(config, &[0u8; 8], &[0u8; 8]), Err(Error::LanesTooFew));
+ }
+
+ #[test]
+ fn new_with_too_many_lanes_returns_correct_error() {
+ let config = Config {
+ lanes: 1 << 24,
+ ..Default::default()
+ };
+ assert_eq!(Context::new(config, &[0u8; 8], &[0u8; 8]), Err(Error::LanesTooMany));
+ }
+
+ #[test]
+ fn new_with_too_short_salt_returns_correct_error() {
+ let config = Default::default();
+ let salt = [0u8; 7];
+ assert_eq!(Context::new(config, &[0u8; 8], &salt), Err(Error::SaltTooShort));
+ }
+
+ #[test]
+ fn new_with_too_short_hash_length_returns_correct_error() {
+ let config = Config {
+ hash_length: 3,
+ ..Default::default()
+ };
+ assert_eq!(Context::new(config, &[0u8; 8], &[0u8; 8]), Err(Error::OutputTooShort));
+ }
+}
diff --git a/third_party/rust/rust-argon2/src/core.rs b/third_party/rust/rust-argon2/src/core.rs
new file mode 100644
index 0000000000..383b392e63
--- /dev/null
+++ b/third_party/rust/rust-argon2/src/core.rs
@@ -0,0 +1,474 @@
+// Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com>
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::block::Block;
+use super::common;
+use super::context::Context;
+use super::memory::Memory;
+use super::variant::Variant;
+use super::version::Version;
+use blake2b_simd::Params;
+use crossbeam_utils::thread::scope;
+use std::mem;
+
+/// Position of the block currently being operated on.
+#[derive(Clone, Debug)]
+struct Position {
+ pass: u32,
+ lane: u32,
+ slice: u32,
+ index: u32,
+}
+
+/// Initializes the memory.
+pub fn initialize(context: &Context, memory: &mut Memory) {
+ fill_first_blocks(context, memory, &mut h0(context));
+}
+
+/// Fills all the memory blocks.
+pub fn fill_memory_blocks(context: &Context, memory: &mut Memory) {
+ if context.config.uses_sequential() {
+ fill_memory_blocks_st(context, memory);
+ } else {
+ fill_memory_blocks_mt(context, memory);
+ }
+}
+
+/// Calculates the final hash and returns it.
+pub fn finalize(context: &Context, memory: &Memory) -> Vec<u8> {
+ let mut blockhash = memory[context.lane_length - 1].clone();
+ for l in 1..context.config.lanes {
+ let last_block_in_lane = l * context.lane_length + (context.lane_length - 1);
+ blockhash ^= &memory[last_block_in_lane];
+ }
+
+ let mut hash = vec![0u8; context.config.hash_length as usize];
+ hprime(hash.as_mut_slice(), blockhash.as_u8());
+ hash
+}
+
+fn blake2b(out: &mut [u8], input: &[&[u8]]) {
+ let mut blake = Params::new().hash_length(out.len()).to_state();
+ for slice in input {
+ blake.update(slice);
+ }
+ out.copy_from_slice(blake.finalize().as_bytes());
+}
+
+fn f_bla_mka(x: u64, y: u64) -> u64 {
+ let m = 0xFFFFFFFFu64;
+ let xy = (x & m) * (y & m);
+ x.wrapping_add(y.wrapping_add(xy.wrapping_add(xy)))
+}
+
+fn fill_block(prev_block: &Block, ref_block: &Block, next_block: &mut Block, with_xor: bool) {
+ let mut block_r = ref_block.clone();
+ block_r ^= prev_block;
+ let mut block_tmp = block_r.clone();
+
+ // Now block_r = ref_block + prev_block and block_tmp = ref_block + prev_block
+ if with_xor {
+ // Saving the next block contents for XOR over
+ block_tmp ^= next_block;
+ // Now block_r = ref_block + prev_block and
+ // block_tmp = ref_block + prev_block + next_block
+ }
+
+ // Apply Blake2 on columns of 64-bit words: (0,1,...,15) , then
+ // (16,17,..31)... finally (112,113,...127)
+ for i in 0..8 {
+ let mut v0 = block_r[16 * i];
+ let mut v1 = block_r[16 * i + 1];
+ let mut v2 = block_r[16 * i + 2];
+ let mut v3 = block_r[16 * i + 3];
+ let mut v4 = block_r[16 * i + 4];
+ let mut v5 = block_r[16 * i + 5];
+ let mut v6 = block_r[16 * i + 6];
+ let mut v7 = block_r[16 * i + 7];
+ let mut v8 = block_r[16 * i + 8];
+ let mut v9 = block_r[16 * i + 9];
+ let mut v10 = block_r[16 * i + 10];
+ let mut v11 = block_r[16 * i + 11];
+ let mut v12 = block_r[16 * i + 12];
+ let mut v13 = block_r[16 * i + 13];
+ let mut v14 = block_r[16 * i + 14];
+ let mut v15 = block_r[16 * i + 15];
+
+ p(
+ &mut v0, &mut v1, &mut v2, &mut v3, &mut v4, &mut v5, &mut v6, &mut v7, &mut v8,
+ &mut v9, &mut v10, &mut v11, &mut v12, &mut v13, &mut v14, &mut v15,
+ );
+
+ block_r[16 * i] = v0;
+ block_r[16 * i + 1] = v1;
+ block_r[16 * i + 2] = v2;
+ block_r[16 * i + 3] = v3;
+ block_r[16 * i + 4] = v4;
+ block_r[16 * i + 5] = v5;
+ block_r[16 * i + 6] = v6;
+ block_r[16 * i + 7] = v7;
+ block_r[16 * i + 8] = v8;
+ block_r[16 * i + 9] = v9;
+ block_r[16 * i + 10] = v10;
+ block_r[16 * i + 11] = v11;
+ block_r[16 * i + 12] = v12;
+ block_r[16 * i + 13] = v13;
+ block_r[16 * i + 14] = v14;
+ block_r[16 * i + 15] = v15;
+ }
+
+ // Apply Blake2 on rows of 64-bit words: (0,1,16,17,...112,113), then
+ // (2,3,18,19,...,114,115).. finally (14,15,30,31,...,126,127)
+ for i in 0..8 {
+ let mut v0 = block_r[2 * i];
+ let mut v1 = block_r[2 * i + 1];
+ let mut v2 = block_r[2 * i + 16];
+ let mut v3 = block_r[2 * i + 17];
+ let mut v4 = block_r[2 * i + 32];
+ let mut v5 = block_r[2 * i + 33];
+ let mut v6 = block_r[2 * i + 48];
+ let mut v7 = block_r[2 * i + 49];
+ let mut v8 = block_r[2 * i + 64];
+ let mut v9 = block_r[2 * i + 65];
+ let mut v10 = block_r[2 * i + 80];
+ let mut v11 = block_r[2 * i + 81];
+ let mut v12 = block_r[2 * i + 96];
+ let mut v13 = block_r[2 * i + 97];
+ let mut v14 = block_r[2 * i + 112];
+ let mut v15 = block_r[2 * i + 113];
+
+ p(
+ &mut v0, &mut v1, &mut v2, &mut v3, &mut v4, &mut v5, &mut v6, &mut v7, &mut v8,
+ &mut v9, &mut v10, &mut v11, &mut v12, &mut v13, &mut v14, &mut v15,
+ );
+
+ block_r[2 * i] = v0;
+ block_r[2 * i + 1] = v1;
+ block_r[2 * i + 16] = v2;
+ block_r[2 * i + 17] = v3;
+ block_r[2 * i + 32] = v4;
+ block_r[2 * i + 33] = v5;
+ block_r[2 * i + 48] = v6;
+ block_r[2 * i + 49] = v7;
+ block_r[2 * i + 64] = v8;
+ block_r[2 * i + 65] = v9;
+ block_r[2 * i + 80] = v10;
+ block_r[2 * i + 81] = v11;
+ block_r[2 * i + 96] = v12;
+ block_r[2 * i + 97] = v13;
+ block_r[2 * i + 112] = v14;
+ block_r[2 * i + 113] = v15;
+ }
+
+ block_tmp.copy_to(next_block);
+ *next_block ^= &block_r;
+}
+
+fn fill_first_blocks(context: &Context, memory: &mut Memory, h0: &mut [u8]) {
+ for lane in 0..context.config.lanes {
+ let start = common::PREHASH_DIGEST_LENGTH;
+ // H'(H0||0||i)
+ h0[start..(start + 4)].clone_from_slice(&u32_as_32le(0));
+ h0[(start + 4)..(start + 8)].clone_from_slice(&u32_as_32le(lane));
+ hprime(memory[(lane, 0)].as_u8_mut(), &h0);
+
+ // H'(H0||1||i)
+ h0[start..(start + 4)].clone_from_slice(&u32_as_32le(1));
+ hprime(memory[(lane, 1)].as_u8_mut(), &h0);
+ }
+}
+
+fn fill_memory_blocks_mt(context: &Context, memory: &mut Memory) {
+ for p in 0..context.config.time_cost {
+ for s in 0..common::SYNC_POINTS {
+ let _ = scope(|scoped| {
+ for (l, mem) in (0..context.config.lanes).zip(memory.as_lanes_mut()) {
+ let position = Position {
+ pass: p,
+ lane: l,
+ slice: s,
+ index: 0,
+ };
+ scoped.spawn(move |_| {
+ fill_segment(context, &position, mem);
+ });
+ }
+ });
+ }
+ }
+}
+
+fn fill_memory_blocks_st(context: &Context, memory: &mut Memory) {
+ for p in 0..context.config.time_cost {
+ for s in 0..common::SYNC_POINTS {
+ for l in 0..context.config.lanes {
+ let position = Position {
+ pass: p,
+ lane: l,
+ slice: s,
+ index: 0,
+ };
+ fill_segment(context, &position, memory);
+ }
+ }
+ }
+}
+
+fn fill_segment(context: &Context, position: &Position, memory: &mut Memory) {
+ let mut position = position.clone();
+ let data_independent_addressing = (context.config.variant == Variant::Argon2i)
+ || (context.config.variant == Variant::Argon2id && position.pass == 0)
+ && (position.slice < (common::SYNC_POINTS / 2));
+ let zero_block = Block::zero();
+ let mut input_block = Block::zero();
+ let mut address_block = Block::zero();
+
+ if data_independent_addressing {
+ input_block[0] = position.pass as u64;
+ input_block[1] = position.lane as u64;
+ input_block[2] = position.slice as u64;
+ input_block[3] = context.memory_blocks as u64;
+ input_block[4] = context.config.time_cost as u64;
+ input_block[5] = context.config.variant.as_u64();
+ }
+
+ let mut starting_index = 0u32;
+
+ if position.pass == 0 && position.slice == 0 {
+ starting_index = 2;
+
+ // Don't forget to generate the first block of addresses:
+ if data_independent_addressing {
+ next_addresses(&mut address_block, &mut input_block, &zero_block);
+ }
+ }
+
+ let mut curr_offset = (position.lane * context.lane_length)
+ + (position.slice * context.segment_length)
+ + starting_index;
+
+ let mut prev_offset = if curr_offset % context.lane_length == 0 {
+ // Last block in this lane
+ curr_offset + context.lane_length - 1
+ } else {
+ curr_offset - 1
+ };
+
+ let mut pseudo_rand;
+ for i in starting_index..context.segment_length {
+ // 1.1 Rotating prev_offset if needed
+ if curr_offset % context.lane_length == 1 {
+ prev_offset = curr_offset - 1;
+ }
+
+ // 1.2 Computing the index of the reference block
+ // 1.2.1 Taking pseudo-random value from the previous block
+ if data_independent_addressing {
+ if i % common::ADDRESSES_IN_BLOCK == 0 {
+ next_addresses(&mut address_block, &mut input_block, &zero_block);
+ }
+ pseudo_rand = address_block[(i % common::ADDRESSES_IN_BLOCK) as usize];
+ } else {
+ pseudo_rand = memory[(prev_offset)][0];
+ }
+
+ // 1.2.2 Computing the lane of the reference block
+ let mut ref_lane = (pseudo_rand >> 32) % context.config.lanes as u64;
+ if (position.pass == 0) && (position.slice == 0) {
+ // Can not reference other lanes yet
+ ref_lane = position.lane as u64;
+ }
+
+ // 1.2.3 Computing the number of possible reference block within the lane.
+ position.index = i;
+ let pseudo_rand_u32 = (pseudo_rand & 0xFFFFFFFF) as u32;
+ let same_lane = ref_lane == (position.lane as u64);
+ let ref_index = index_alpha(context, &position, pseudo_rand_u32, same_lane);
+
+ // 2 Creating a new block
+ let index = context.lane_length as u64 * ref_lane + ref_index as u64;
+ let mut curr_block = memory[curr_offset].clone();
+ {
+ let ref prev_block = memory[prev_offset];
+ let ref ref_block = memory[index];
+ if context.config.version == Version::Version10 {
+ fill_block(prev_block, ref_block, &mut curr_block, false);
+ } else {
+ if position.pass == 0 {
+ fill_block(prev_block, ref_block, &mut curr_block, false);
+ } else {
+ fill_block(prev_block, ref_block, &mut curr_block, true);
+ }
+ }
+ }
+
+ memory[curr_offset] = curr_block;
+ curr_offset += 1;
+ prev_offset += 1;
+ }
+}
+
+fn g(a: &mut u64, b: &mut u64, c: &mut u64, d: &mut u64) {
+ *a = f_bla_mka(*a, *b);
+ *d = rotr64(*d ^ *a, 32);
+ *c = f_bla_mka(*c, *d);
+ *b = rotr64(*b ^ *c, 24);
+ *a = f_bla_mka(*a, *b);
+ *d = rotr64(*d ^ *a, 16);
+ *c = f_bla_mka(*c, *d);
+ *b = rotr64(*b ^ *c, 63);
+}
+
+fn h0(context: &Context) -> [u8; common::PREHASH_SEED_LENGTH] {
+ let input = [
+ &u32_as_32le(context.config.lanes),
+ &u32_as_32le(context.config.hash_length),
+ &u32_as_32le(context.config.mem_cost),
+ &u32_as_32le(context.config.time_cost),
+ &u32_as_32le(context.config.version.as_u32()),
+ &u32_as_32le(context.config.variant.as_u32()),
+ &len_as_32le(context.pwd),
+ context.pwd.as_ref(),
+ &len_as_32le(context.salt),
+ context.salt.as_ref(),
+ &len_as_32le(context.config.secret),
+ context.config.secret.as_ref(),
+ &len_as_32le(context.config.ad),
+ context.config.ad.as_ref(),
+ ];
+ let mut out = [0u8; common::PREHASH_SEED_LENGTH];
+ blake2b(&mut out[0..common::PREHASH_DIGEST_LENGTH], &input);
+ out
+}
+
+fn hprime(out: &mut [u8], input: &[u8]) {
+ let out_len = out.len();
+ if out_len <= common::BLAKE2B_OUT_LENGTH {
+ blake2b(out, &[&u32_as_32le(out_len as u32), input]);
+ } else {
+ let ai_len = 32;
+ let mut out_buffer = [0u8; common::BLAKE2B_OUT_LENGTH];
+ let mut in_buffer = [0u8; common::BLAKE2B_OUT_LENGTH];
+ blake2b(&mut out_buffer, &[&u32_as_32le(out_len as u32), input]);
+ out[0..ai_len].clone_from_slice(&out_buffer[0..ai_len]);
+ let mut out_pos = ai_len;
+ let mut to_produce = out_len - ai_len;
+
+ while to_produce > common::BLAKE2B_OUT_LENGTH {
+ in_buffer.clone_from_slice(&out_buffer);
+ blake2b(&mut out_buffer, &[&in_buffer]);
+ out[out_pos..out_pos + ai_len].clone_from_slice(&out_buffer[0..ai_len]);
+ out_pos += ai_len;
+ to_produce -= ai_len;
+ }
+ blake2b(&mut out[out_pos..out_len], &[&out_buffer]);
+ }
+}
+
+fn index_alpha(context: &Context, position: &Position, pseudo_rand: u32, same_lane: bool) -> u32 {
+ // Pass 0:
+ // - This lane: all already finished segments plus already constructed blocks in this segment
+ // - Other lanes: all already finished segments
+ // Pass 1+:
+ // - This lane: (SYNC_POINTS - 1) last segments plus already constructed blocks in this segment
+ // - Other lanes : (SYNC_POINTS - 1) last segments
+ let reference_area_size: u32 = if position.pass == 0 {
+ // First pass
+ if position.slice == 0 {
+ // First slice
+ position.index - 1
+ } else {
+ if same_lane {
+ // The same lane => add current segment
+ position.slice * context.segment_length + position.index - 1
+ } else {
+ if position.index == 0 {
+ position.slice * context.segment_length - 1
+ } else {
+ position.slice * context.segment_length
+ }
+ }
+ }
+ } else {
+ // Second pass
+ if same_lane {
+ context.lane_length - context.segment_length + position.index - 1
+ } else {
+ if position.index == 0 {
+ context.lane_length - context.segment_length - 1
+ } else {
+ context.lane_length - context.segment_length
+ }
+ }
+ };
+ let reference_area_size = reference_area_size as u64;
+ let mut relative_position = pseudo_rand as u64;
+ relative_position = relative_position * relative_position >> 32;
+ relative_position = reference_area_size - 1 - (reference_area_size * relative_position >> 32);
+
+ // 1.2.5 Computing starting position
+ let start_position: u32 = if position.pass != 0 {
+ if position.slice == common::SYNC_POINTS - 1 {
+ 0u32
+ } else {
+ (position.slice + 1) * context.segment_length
+ }
+ } else {
+ 0u32
+ };
+ let start_position = start_position as u64;
+
+ // 1.2.6. Computing absolute position
+ ((start_position + relative_position) % context.lane_length as u64) as u32
+}
+
+fn len_as_32le(slice: &[u8]) -> [u8; 4] {
+ u32_as_32le(slice.len() as u32)
+}
+
+fn next_addresses(address_block: &mut Block, input_block: &mut Block, zero_block: &Block) {
+ input_block[6] += 1;
+ fill_block(zero_block, input_block, address_block, false);
+ fill_block(zero_block, &address_block.clone(), address_block, false);
+}
+
+fn p(
+ v0: &mut u64,
+ v1: &mut u64,
+ v2: &mut u64,
+ v3: &mut u64,
+ v4: &mut u64,
+ v5: &mut u64,
+ v6: &mut u64,
+ v7: &mut u64,
+ v8: &mut u64,
+ v9: &mut u64,
+ v10: &mut u64,
+ v11: &mut u64,
+ v12: &mut u64,
+ v13: &mut u64,
+ v14: &mut u64,
+ v15: &mut u64,
+) {
+ g(v0, v4, v8, v12);
+ g(v1, v5, v9, v13);
+ g(v2, v6, v10, v14);
+ g(v3, v7, v11, v15);
+ g(v0, v5, v10, v15);
+ g(v1, v6, v11, v12);
+ g(v2, v7, v8, v13);
+ g(v3, v4, v9, v14);
+}
+
+fn rotr64(w: u64, c: u32) -> u64 {
+ (w >> c) | (w << (64 - c))
+}
+
+fn u32_as_32le(val: u32) -> [u8; 4] {
+ unsafe { mem::transmute(val.to_le()) }
+}
diff --git a/third_party/rust/rust-argon2/src/decoded.rs b/third_party/rust/rust-argon2/src/decoded.rs
new file mode 100644
index 0000000000..2a83769e14
--- /dev/null
+++ b/third_party/rust/rust-argon2/src/decoded.rs
@@ -0,0 +1,35 @@
+// Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com>
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use version::Version;
+use variant::Variant;
+
+/// Structure that contains the decoded data.
+#[derive(Debug, Eq, PartialEq)]
+pub struct Decoded {
+ /// The variant.
+ pub variant: Variant,
+
+ /// The version.
+ pub version: Version,
+
+ /// The amount of memory requested (KiB).
+ pub mem_cost: u32,
+
+ /// The number of passes.
+ pub time_cost: u32,
+
+ /// The parallelism.
+ pub parallelism: u32,
+
+ /// The salt.
+ pub salt: Vec<u8>,
+
+ /// The hash.
+ pub hash: Vec<u8>,
+}
diff --git a/third_party/rust/rust-argon2/src/encoding.rs b/third_party/rust/rust-argon2/src/encoding.rs
new file mode 100644
index 0000000000..7f0d9cd705
--- /dev/null
+++ b/third_party/rust/rust-argon2/src/encoding.rs
@@ -0,0 +1,401 @@
+// Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com>
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use base64;
+use super::context::Context;
+use super::decoded::Decoded;
+use super::error::Error;
+use super::result::Result;
+use super::variant::Variant;
+use super::version::Version;
+
+/// Structure containing the options.
+struct Options {
+ mem_cost: u32,
+ time_cost: u32,
+ parallelism: u32,
+}
+
+/// Gets the base64 encoded length of a byte slice with the specified length.
+pub fn base64_len(length: u32) -> u32 {
+ let olen = (length / 3) << 2;
+ match length % 3 {
+ 2 => olen + 3,
+ 1 => olen + 2,
+ _ => olen,
+ }
+}
+
+/// Attempts to decode the encoded string slice.
+pub fn decode_string(encoded: &str) -> Result<Decoded> {
+ let items: Vec<&str> = encoded.split('$').collect();
+ if items.len() == 6 {
+ decode_empty(items[0])?;
+ let variant = decode_variant(items[1])?;
+ let version = decode_version(items[2])?;
+ let options = decode_options(items[3])?;
+ let salt = base64::decode(items[4])?;
+ let hash = base64::decode(items[5])?;
+
+ Ok(Decoded {
+ variant: variant,
+ version: version,
+ mem_cost: options.mem_cost,
+ time_cost: options.time_cost,
+ parallelism: options.parallelism,
+ salt: salt,
+ hash: hash,
+ })
+ } else if items.len() == 5 {
+ decode_empty(items[0])?;
+ let variant = decode_variant(items[1])?;
+ let options = decode_options(items[2])?;
+ let salt = base64::decode(items[3])?;
+ let hash = base64::decode(items[4])?;
+
+ Ok(Decoded {
+ variant: variant,
+ version: Version::Version10,
+ mem_cost: options.mem_cost,
+ time_cost: options.time_cost,
+ parallelism: options.parallelism,
+ salt: salt,
+ hash: hash,
+ })
+ } else {
+ return Err(Error::DecodingFail);
+ }
+
+}
+
+fn decode_empty(str: &str) -> Result<()> {
+ if str == "" {
+ Ok(())
+ } else {
+ Err(Error::DecodingFail)
+ }
+}
+
+fn decode_options(str: &str) -> Result<Options> {
+ let items: Vec<&str> = str.split(',').collect();
+ if items.len() == 3 {
+ Ok(Options {
+ mem_cost: decode_option(items[0], "m")?,
+ time_cost: decode_option(items[1], "t")?,
+ parallelism: decode_option(items[2], "p")?,
+ })
+ } else {
+ Err(Error::DecodingFail)
+ }
+}
+
+fn decode_option(str: &str, name: &str) -> Result<u32> {
+ let items: Vec<&str> = str.split('=').collect();
+ if items.len() == 2 {
+ if items[0] == name {
+ decode_u32(items[1])
+ } else {
+ Err(Error::DecodingFail)
+ }
+ } else {
+ Err(Error::DecodingFail)
+ }
+}
+
+fn decode_u32(str: &str) -> Result<u32> {
+ match str.parse() {
+ Ok(i) => Ok(i),
+ Err(_) => Err(Error::DecodingFail),
+ }
+}
+
+fn decode_variant(str: &str) -> Result<Variant> {
+ Variant::from_str(str)
+}
+
+fn decode_version(str: &str) -> Result<Version> {
+ let items: Vec<&str> = str.split('=').collect();
+ if items.len() == 2 {
+ if items[0] == "v" {
+ Version::from_str(items[1])
+ } else {
+ Err(Error::DecodingFail)
+ }
+ } else {
+ Err(Error::DecodingFail)
+ }
+}
+
+/// Encodes the hash and context.
+pub fn encode_string(context: &Context, hash: &Vec<u8>) -> String {
+ format!(
+ "${}$v={}$m={},t={},p={}${}${}",
+ context.config.variant,
+ context.config.version,
+ context.config.mem_cost,
+ context.config.time_cost,
+ context.config.lanes,
+ base64::encode_config(context.salt, base64::STANDARD_NO_PAD),
+ base64::encode_config(hash, base64::STANDARD_NO_PAD),
+ )
+}
+
+/// Gets the string length of the specified number.
+pub fn num_len(number: u32) -> u32 {
+ let mut len = 1;
+ let mut num = number;
+ while num >= 10 {
+ len += 1;
+ num /= 10;
+ }
+ len
+}
+
+
+#[cfg(test)]
+mod tests {
+
+ use config::Config;
+ use context::Context;
+ use decoded::Decoded;
+ use error::Error;
+ use thread_mode::ThreadMode;
+ use variant::Variant;
+ use version::Version;
+ use super::*;
+
+ #[test]
+ fn base64_len_returns_correct_length() {
+ let tests = vec![
+ (1, 2),
+ (2, 3),
+ (3, 4),
+ (4, 6),
+ (5, 7),
+ (6, 8),
+ (7, 10),
+ (8, 11),
+ (9, 12),
+ (10, 14),
+ ];
+ for (len, expected) in tests {
+ let actual = base64_len(len);
+ assert_eq!(actual, expected);
+ }
+ }
+
+ #[test]
+ fn decode_string_with_version10_returns_correct_result() {
+ let encoded = "$argon2i$v=16$m=4096,t=3,p=1\
+ $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
+ let expected = Decoded {
+ variant: Variant::Argon2i,
+ version: Version::Version10,
+ mem_cost: 4096,
+ time_cost: 3,
+ parallelism: 1,
+ salt: b"salt1234".to_vec(),
+ hash: b"12345678901234567890123456789012".to_vec(),
+ };
+ let actual = decode_string(encoded).unwrap();
+ assert_eq!(actual, expected);
+ }
+
+ #[test]
+ fn decode_string_with_version13_returns_correct_result() {
+ let encoded = "$argon2i$v=19$m=4096,t=3,p=1\
+ $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
+ let expected = Decoded {
+ variant: Variant::Argon2i,
+ version: Version::Version13,
+ mem_cost: 4096,
+ time_cost: 3,
+ parallelism: 1,
+ salt: b"salt1234".to_vec(),
+ hash: b"12345678901234567890123456789012".to_vec(),
+ };
+ let actual = decode_string(encoded).unwrap();
+ assert_eq!(actual, expected);
+ }
+
+ #[test]
+ fn decode_string_without_version_returns_correct_result() {
+ let encoded = "$argon2i$m=4096,t=3,p=1\
+ $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
+ let expected = Decoded {
+ variant: Variant::Argon2i,
+ version: Version::Version10,
+ mem_cost: 4096,
+ time_cost: 3,
+ parallelism: 1,
+ salt: b"salt1234".to_vec(),
+ hash: b"12345678901234567890123456789012".to_vec(),
+ };
+ let actual = decode_string(encoded).unwrap();
+ assert_eq!(actual, expected);
+ }
+
+ #[test]
+ fn decode_string_without_variant_returns_error_result() {
+ let encoded = "$m=4096,t=3,p=1\
+ $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
+ let result = decode_string(encoded);
+ assert_eq!(result, Err(Error::DecodingFail));
+ }
+
+ #[test]
+ fn decode_string_with_empty_variant_returns_error_result() {
+ let encoded = "$$m=4096,t=3,p=1\
+ $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
+ let result = decode_string(encoded);
+ assert_eq!(result, Err(Error::DecodingFail));
+ }
+
+ #[test]
+ fn decode_string_with_invalid_variant_returns_error_result() {
+ let encoded = "$argon$m=4096,t=3,p=1\
+ $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
+ let result = decode_string(encoded);
+ assert_eq!(result, Err(Error::DecodingFail));
+ }
+
+ #[test]
+ fn decode_string_without_mem_cost_returns_error_result() {
+ let encoded = "$argon2i$t=3,p=1\
+ $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
+ let result = decode_string(encoded);
+ assert_eq!(result, Err(Error::DecodingFail));
+ }
+
+ #[test]
+ fn decode_string_with_empty_mem_cost_returns_error_result() {
+ let encoded = "$argon2i$m=,t=3,p=1\
+ $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
+ let result = decode_string(encoded);
+ assert_eq!(result, Err(Error::DecodingFail));
+ }
+
+ #[test]
+ fn decode_string_with_non_numeric_mem_cost_returns_error_result() {
+ let encoded = "$argon2i$m=a,t=3,p=1\
+ $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
+ let result = decode_string(encoded);
+ assert_eq!(result, Err(Error::DecodingFail));
+ }
+
+ #[test]
+ fn decode_string_without_time_cost_returns_error_result() {
+ let encoded = "$argon2i$m=4096,p=1\
+ $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
+ let result = decode_string(encoded);
+ assert_eq!(result, Err(Error::DecodingFail));
+ }
+
+ #[test]
+ fn decode_string_with_empty_time_cost_returns_error_result() {
+ let encoded = "$argon2i$m=4096,t=,p=1\
+ $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
+ let result = decode_string(encoded);
+ assert_eq!(result, Err(Error::DecodingFail));
+ }
+
+ #[test]
+ fn decode_string_with_non_numeric_time_cost_returns_error_result() {
+ let encoded = "$argon2i$m=4096,t=a,p=1\
+ $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
+ let result = decode_string(encoded);
+ assert_eq!(result, Err(Error::DecodingFail));
+ }
+
+ #[test]
+ fn decode_string_without_parallelism_returns_error_result() {
+ let encoded = "$argon2i$m=4096,t=3\
+ $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
+ let result = decode_string(encoded);
+ assert_eq!(result, Err(Error::DecodingFail));
+ }
+
+ #[test]
+ fn decode_string_with_empty_parallelism_returns_error_result() {
+ let encoded = "$argon2i$m=4096,t=3,p=\
+ $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
+ let result = decode_string(encoded);
+ assert_eq!(result, Err(Error::DecodingFail));
+ }
+
+ #[test]
+ fn decode_string_with_non_numeric_parallelism_returns_error_result() {
+ let encoded = "$argon2i$m=4096,t=3,p=a\
+ $c2FsdDEyMzQ=$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
+ let result = decode_string(encoded);
+ assert_eq!(result, Err(Error::DecodingFail));
+ }
+
+ #[test]
+ fn decode_string_without_salt_returns_error_result() {
+ let encoded = "$argon2i$m=4096,t=3,p=1\
+ $MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI=";
+ let result = decode_string(encoded);
+ assert_eq!(result, Err(Error::DecodingFail));
+ }
+
+ #[test]
+ fn decode_string_without_hash_returns_error_result() {
+ let encoded = "$argon2i$m=4096,t=3,p=a\
+ $c2FsdDEyMzQ=";
+ let result = decode_string(encoded);
+ assert_eq!(result, Err(Error::DecodingFail));
+ }
+
+ #[test]
+ fn decode_string_with_empty_hash_returns_error_result() {
+ let encoded = "$argon2i$m=4096,t=3,p=a\
+ $c2FsdDEyMzQ=$";
+ let result = decode_string(encoded);
+ assert_eq!(result, Err(Error::DecodingFail));
+ }
+
+ #[test]
+ fn encode_string_returns_correct_string() {
+ let hash = b"12345678901234567890123456789012".to_vec();
+ let config = Config {
+ ad: &[],
+ hash_length: hash.len() as u32,
+ lanes: 1,
+ mem_cost: 4096,
+ secret: &[],
+ thread_mode: ThreadMode::Parallel,
+ time_cost: 3,
+ variant: Variant::Argon2i,
+ version: Version::Version13,
+ };
+ let pwd = b"password".to_vec();
+ let salt = b"salt1234".to_vec();
+ let context = Context::new(config, &pwd, &salt).unwrap();
+ let expected = "$argon2i$v=19$m=4096,t=3,p=1\
+ $c2FsdDEyMzQ$MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI";
+ let actual = encode_string(&context, &hash);
+ assert_eq!(actual, expected);
+ }
+
+ #[test]
+ fn num_len_returns_correct_length() {
+ let tests = vec![
+ (1, 1),
+ (10, 2),
+ (110, 3),
+ (1230, 4),
+ (12340, 5),
+ (123457, 6),
+ ];
+ for (num, expected) in tests {
+ let actual = num_len(num);
+ assert_eq!(actual, expected);
+ }
+ }
+}
diff --git a/third_party/rust/rust-argon2/src/error.rs b/third_party/rust/rust-argon2/src/error.rs
new file mode 100644
index 0000000000..53d7b5a940
--- /dev/null
+++ b/third_party/rust/rust-argon2/src/error.rs
@@ -0,0 +1,119 @@
+// Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com>
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use base64;
+use std::{error, fmt};
+
+/// Error type for Argon2 errors.
+#[derive(Debug, PartialEq)]
+pub enum Error {
+ /// The output (hash) is too short (minimum is 4).
+ OutputTooShort,
+
+ /// The output (hash) is too long (maximum is 2^32 - 1).
+ OutputTooLong,
+
+ /// The password is too short (minimum is 0).
+ PwdTooShort,
+
+ /// The password is too long (maximum is 2^32 - 1).
+ PwdTooLong,
+
+ /// The salt is too short (minimum is 8).
+ SaltTooShort,
+
+ /// The salt is too long (maximum is 2^32 - 1).
+ SaltTooLong,
+
+ /// The associated data is too short (minimum is 0).
+ AdTooShort,
+
+ /// The associated data is too long (maximum is 2^32 - 1).
+ AdTooLong,
+
+ /// The secret value is too short (minimum is 0).
+ SecretTooShort,
+
+ /// The secret value is too long (maximum is 2^32 - 1).
+ SecretTooLong,
+
+ /// The time cost (passes) is too small (minimum is 1).
+ TimeTooSmall,
+
+ /// The time cost (passes) is too large (maximum is 2^32 - 1).
+ TimeTooLarge,
+
+ /// The memory cost is too small (minimum is 8 x parallelism).
+ MemoryTooLittle,
+
+ /// The memory cost is too large (maximum 2GiB on 32-bit or 4TiB on 64-bit).
+ MemoryTooMuch,
+
+ /// The number of lanes (parallelism) is too small (minimum is 1).
+ LanesTooFew,
+
+ /// The number of lanes (parallelism) is too large (maximum is 2^24 - 1).
+ LanesTooMany,
+
+ /// Incorrect Argon2 variant.
+ IncorrectType,
+
+ /// Incorrect Argon2 version.
+ IncorrectVersion,
+
+ /// The decoding of the encoded data has failed.
+ DecodingFail,
+}
+
+impl Error {
+ fn msg(&self) -> &str {
+ match *self {
+ Error::OutputTooShort => "Output is too short",
+ Error::OutputTooLong => "Output is too long",
+ Error::PwdTooShort => "Password is too short",
+ Error::PwdTooLong => "Password is too long",
+ Error::SaltTooShort => "Salt is too short",
+ Error::SaltTooLong => "Salt is too long",
+ Error::AdTooShort => "Associated data is too short",
+ Error::AdTooLong => "Associated data is too long",
+ Error::SecretTooShort => "Secret is too short",
+ Error::SecretTooLong => "Secret is too long",
+ Error::TimeTooSmall => "Time cost is too small",
+ Error::TimeTooLarge => "Time cost is too large",
+ Error::MemoryTooLittle => "Memory cost is too small",
+ Error::MemoryTooMuch => "Memory cost is too large",
+ Error::LanesTooFew => "Too few lanes",
+ Error::LanesTooMany => "Too many lanes",
+ Error::IncorrectType => "There is no such type of Argon2",
+ Error::IncorrectVersion => "There is no such version of Argon2",
+ Error::DecodingFail => "Decoding failed",
+ }
+ }
+}
+
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.msg())
+ }
+}
+
+impl error::Error for Error {
+ fn description(&self) -> &str {
+ self.msg()
+ }
+
+ fn cause(&self) -> Option<&error::Error> {
+ None
+ }
+}
+
+impl From<base64::DecodeError> for Error {
+ fn from(_: base64::DecodeError) -> Self {
+ Error::DecodingFail
+ }
+}
diff --git a/third_party/rust/rust-argon2/src/lib.rs b/third_party/rust/rust-argon2/src/lib.rs
new file mode 100644
index 0000000000..d871811ae2
--- /dev/null
+++ b/third_party/rust/rust-argon2/src/lib.rs
@@ -0,0 +1,103 @@
+// Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com>
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Library for hashing passwords using
+//! [Argon2](https://github.com/P-H-C/phc-winner-argon2), the password-hashing
+//! function that won the
+//! [Password Hashing Competition (PHC)](https://password-hashing.net).
+//!
+//! # Usage
+//!
+//! To use this crate, add the following to your Cargo.toml:
+//!
+//! ```toml
+//! [dependencies]
+//! rust-argon2 = "0.5"
+//! ```
+//!
+//! And the following to your crate root:
+//!
+//! ```rust
+//! extern crate argon2;
+//! ```
+//!
+//! # Examples
+//!
+//! Create a password hash using the defaults and verify it:
+//!
+//! ```rust
+//! use argon2::{self, Config};
+//!
+//! let password = b"password";
+//! let salt = b"randomsalt";
+//! let config = Config::default();
+//! let hash = argon2::hash_encoded(password, salt, &config).unwrap();
+//! let matches = argon2::verify_encoded(&hash, password).unwrap();
+//! assert!(matches);
+//! ```
+//!
+//! Create a password hash with custom settings and verify it:
+//!
+//! ```rust
+//! use argon2::{self, Config, ThreadMode, Variant, Version};
+//!
+//! let password = b"password";
+//! let salt = b"othersalt";
+//! let config = Config {
+//! variant: Variant::Argon2i,
+//! version: Version::Version13,
+//! mem_cost: 65536,
+//! time_cost: 10,
+//! lanes: 4,
+//! thread_mode: ThreadMode::Parallel,
+//! secret: &[],
+//! ad: &[],
+//! hash_length: 32
+//! };
+//! let hash = argon2::hash_encoded(password, salt, &config).unwrap();
+//! let matches = argon2::verify_encoded(&hash, password).unwrap();
+//! assert!(matches);
+//! ```
+//!
+//! # Limitations
+//!
+//! This crate has the same limitation as the `blake2-rfc` crate that it uses.
+//! It does not attempt to clear potentially sensitive data from its work
+//! memory. To do so correctly without a heavy performance penalty would
+//! require help from the compiler. It's better to not attempt to do so than to
+//! present a false assurance.
+//!
+//! This version uses the standard implementation and does not yet implement
+//! optimizations. Therefore, it is not the fastest implementation available.
+
+extern crate base64;
+extern crate blake2b_simd;
+extern crate crossbeam_utils;
+
+mod argon2;
+mod block;
+mod common;
+mod config;
+mod context;
+mod core;
+mod decoded;
+mod encoding;
+mod error;
+mod memory;
+mod result;
+mod thread_mode;
+mod variant;
+mod version;
+
+pub use argon2::*;
+pub use config::Config;
+pub use error::Error;
+pub use result::Result;
+pub use thread_mode::ThreadMode;
+pub use variant::Variant;
+pub use version::Version;
diff --git a/third_party/rust/rust-argon2/src/memory.rs b/third_party/rust/rust-argon2/src/memory.rs
new file mode 100644
index 0000000000..85f0c3313e
--- /dev/null
+++ b/third_party/rust/rust-argon2/src/memory.rs
@@ -0,0 +1,120 @@
+// Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com>
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::fmt;
+use std::fmt::Debug;
+use std::ops::{Index, IndexMut};
+use super::block::Block;
+
+/// Structure representing the memory matrix.
+pub struct Memory {
+ /// The number of rows.
+ rows: usize,
+
+ /// The number of columns.
+ cols: usize,
+
+ /// The flat array of blocks representing the memory matrix.
+ blocks: Box<[Block]>,
+}
+
+impl Memory {
+ /// Creates a new memory matrix.
+ pub fn new(lanes: u32, lane_length: u32) -> Memory {
+ let rows = lanes as usize;
+ let cols = lane_length as usize;
+ let total = rows * cols;
+ let blocks = vec![Block::zero(); total].into_boxed_slice();
+ Memory {
+ rows: rows,
+ cols: cols,
+ blocks: blocks,
+ }
+ }
+
+ /// Gets the mutable lanes representation of the memory matrix.
+ pub fn as_lanes_mut(&mut self) -> Vec<&mut Memory> {
+ let ptr: *mut Memory = self;
+ let mut vec = Vec::with_capacity(self.rows);
+ for _ in 0..self.rows {
+ vec.push(unsafe { &mut (*ptr) });
+ }
+ vec
+ }
+}
+
+impl Debug for Memory {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "Memory {{ rows: {}, cols: {} }}", self.rows, self.cols)
+ }
+}
+
+impl Index<u32> for Memory {
+ type Output = Block;
+ fn index(&self, index: u32) -> &Block {
+ &self.blocks[index as usize]
+ }
+}
+
+impl Index<u64> for Memory {
+ type Output = Block;
+ fn index(&self, index: u64) -> &Block {
+ &self.blocks[index as usize]
+ }
+}
+
+impl Index<(u32, u32)> for Memory {
+ type Output = Block;
+ fn index(&self, index: (u32, u32)) -> &Block {
+ let pos = ((index.0 as usize) * self.cols) + (index.1 as usize);
+ &self.blocks[pos]
+ }
+}
+
+impl IndexMut<u32> for Memory {
+ fn index_mut(&mut self, index: u32) -> &mut Block {
+ &mut self.blocks[index as usize]
+ }
+}
+
+impl IndexMut<u64> for Memory {
+ fn index_mut(&mut self, index: u64) -> &mut Block {
+ &mut self.blocks[index as usize]
+ }
+}
+
+impl IndexMut<(u32, u32)> for Memory {
+ fn index_mut(&mut self, index: (u32, u32)) -> &mut Block {
+ let pos = ((index.0 as usize) * self.cols) + (index.1 as usize);
+ &mut self.blocks[pos]
+ }
+}
+
+
+#[cfg(test)]
+mod tests {
+
+ use super::*;
+
+ #[test]
+ fn new_returns_correct_instance() {
+ let lanes = 4;
+ let lane_length = 128;
+ let memory = Memory::new(lanes, lane_length);
+ assert_eq!(memory.rows, lanes as usize);
+ assert_eq!(memory.cols, lane_length as usize);
+ assert_eq!(memory.blocks.len(), 512);
+ }
+
+ #[test]
+ fn as_lanes_mut_returns_correct_vec() {
+ let mut memory = Memory::new(4, 128);
+ let lanes = memory.as_lanes_mut();
+ assert_eq!(lanes.len(), 4);
+ }
+}
diff --git a/third_party/rust/rust-argon2/src/result.rs b/third_party/rust/rust-argon2/src/result.rs
new file mode 100644
index 0000000000..f89c55815c
--- /dev/null
+++ b/third_party/rust/rust-argon2/src/result.rs
@@ -0,0 +1,13 @@
+// Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com>
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::result;
+use super::error::Error;
+
+/// A specialized result type for Argon2 operations.
+pub type Result<T> = result::Result<T, Error>;
diff --git a/third_party/rust/rust-argon2/src/thread_mode.rs b/third_party/rust/rust-argon2/src/thread_mode.rs
new file mode 100644
index 0000000000..0775c4d830
--- /dev/null
+++ b/third_party/rust/rust-argon2/src/thread_mode.rs
@@ -0,0 +1,56 @@
+// Copyright (c) 2017 Xidorn Quan <me@upsuper.org>
+// Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com>
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// The thread mode used to perform the hashing.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum ThreadMode {
+ /// Run in one thread.
+ Sequential,
+
+ /// Run in the same number of threads as the number of lanes.
+ Parallel,
+}
+
+impl ThreadMode {
+ /// Create a thread mode from the threads count.
+ pub fn from_threads(threads: u32) -> ThreadMode {
+ if threads > 1 {
+ ThreadMode::Parallel
+ } else {
+ ThreadMode::Sequential
+ }
+ }
+}
+
+impl Default for ThreadMode {
+ fn default() -> ThreadMode {
+ ThreadMode::Sequential
+ }
+}
+
+
+#[cfg(test)]
+mod tests {
+
+ use super::*;
+
+ #[test]
+ fn default_returns_correct_thread_mode() {
+ assert_eq!(ThreadMode::default(), ThreadMode::Sequential);
+ }
+
+ #[test]
+ fn from_threads_returns_correct_thread_mode() {
+ assert_eq!(ThreadMode::from_threads(0), ThreadMode::Sequential);
+ assert_eq!(ThreadMode::from_threads(1), ThreadMode::Sequential);
+ assert_eq!(ThreadMode::from_threads(2), ThreadMode::Parallel);
+ assert_eq!(ThreadMode::from_threads(10), ThreadMode::Parallel);
+ assert_eq!(ThreadMode::from_threads(100), ThreadMode::Parallel);
+ }
+}
diff --git a/third_party/rust/rust-argon2/src/variant.rs b/third_party/rust/rust-argon2/src/variant.rs
new file mode 100644
index 0000000000..8fb6c0b54c
--- /dev/null
+++ b/third_party/rust/rust-argon2/src/variant.rs
@@ -0,0 +1,159 @@
+// Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com>
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::fmt;
+use super::error::Error;
+use super::result::Result;
+
+/// The Argon2 variant.
+#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
+pub enum Variant {
+ /// Argon2 using data-dependent memory access to thwart tradeoff attacks.
+ /// Recommended for cryptocurrencies and backend servers.
+ Argon2d = 0,
+
+ /// Argon2 using data-independent memory access to thwart side-channel
+ /// attacks. Recommended for password hashing and password-based key
+ /// derivation.
+ Argon2i = 1,
+
+ /// Argon2 using hybrid construction.
+ Argon2id = 2,
+}
+
+impl Variant {
+ /// Gets the lowercase string slice representation of the variant.
+ pub fn as_lowercase_str(&self) -> &'static str {
+ match *self {
+ Variant::Argon2d => "argon2d",
+ Variant::Argon2i => "argon2i",
+ Variant::Argon2id => "argon2id",
+ }
+ }
+
+ /// Gets the u32 representation of the variant.
+ pub fn as_u32(&self) -> u32 {
+ *self as u32
+ }
+
+ /// Gets the u64 representation of the variant.
+ pub fn as_u64(&self) -> u64 {
+ *self as u64
+ }
+
+ /// Gets the uppercase string slice representation of the variant.
+ pub fn as_uppercase_str(&self) -> &'static str {
+ match *self {
+ Variant::Argon2d => "Argon2d",
+ Variant::Argon2i => "Argon2i",
+ Variant::Argon2id => "Argon2id",
+ }
+ }
+
+ /// Attempts to create a variant from a string slice.
+ pub fn from_str(str: &str) -> Result<Variant> {
+ match str {
+ "Argon2d" => Ok(Variant::Argon2d),
+ "Argon2i" => Ok(Variant::Argon2i),
+ "Argon2id" => Ok(Variant::Argon2id),
+ "argon2d" => Ok(Variant::Argon2d),
+ "argon2i" => Ok(Variant::Argon2i),
+ "argon2id" => Ok(Variant::Argon2id),
+ _ => Err(Error::DecodingFail),
+ }
+ }
+
+ /// Attempts to create a variant from an u32.
+ pub fn from_u32(val: u32) -> Result<Variant> {
+ match val {
+ 0 => Ok(Variant::Argon2d),
+ 1 => Ok(Variant::Argon2i),
+ 2 => Ok(Variant::Argon2id),
+ _ => Err(Error::IncorrectType),
+ }
+ }
+}
+
+impl Default for Variant {
+ fn default() -> Variant {
+ Variant::Argon2i
+ }
+}
+
+impl fmt::Display for Variant {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.as_lowercase_str())
+ }
+}
+
+
+#[cfg(test)]
+mod tests {
+
+ use error::Error;
+ use super::*;
+
+ #[test]
+ fn as_lowercase_str_returns_correct_str() {
+ assert_eq!(Variant::Argon2d.as_lowercase_str(), "argon2d");
+ assert_eq!(Variant::Argon2i.as_lowercase_str(), "argon2i");
+ assert_eq!(Variant::Argon2id.as_lowercase_str(), "argon2id");
+ }
+
+ #[test]
+ fn as_u32_returns_correct_u32() {
+ assert_eq!(Variant::Argon2d.as_u32(), 0);
+ assert_eq!(Variant::Argon2i.as_u32(), 1);
+ assert_eq!(Variant::Argon2id.as_u32(), 2);
+ }
+
+ #[test]
+ fn as_u64_returns_correct_u64() {
+ assert_eq!(Variant::Argon2d.as_u64(), 0);
+ assert_eq!(Variant::Argon2i.as_u64(), 1);
+ assert_eq!(Variant::Argon2id.as_u64(), 2);
+ }
+
+ #[test]
+ fn as_uppercase_str_returns_correct_str() {
+ assert_eq!(Variant::Argon2d.as_uppercase_str(), "Argon2d");
+ assert_eq!(Variant::Argon2i.as_uppercase_str(), "Argon2i");
+ assert_eq!(Variant::Argon2id.as_uppercase_str(), "Argon2id");
+ }
+
+ #[test]
+ fn default_returns_correct_variant() {
+ assert_eq!(Variant::default(), Variant::Argon2i);
+ }
+
+ #[test]
+ fn display_returns_correct_string() {
+ assert_eq!(format!("{}", Variant::Argon2d), "argon2d");
+ assert_eq!(format!("{}", Variant::Argon2i), "argon2i");
+ assert_eq!(format!("{}", Variant::Argon2id), "argon2id");
+ }
+
+ #[test]
+ fn from_str_returns_correct_result() {
+ assert_eq!(Variant::from_str("Argon2d"), Ok(Variant::Argon2d));
+ assert_eq!(Variant::from_str("Argon2i"), Ok(Variant::Argon2i));
+ assert_eq!(Variant::from_str("Argon2id"), Ok(Variant::Argon2id));
+ assert_eq!(Variant::from_str("argon2d"), Ok(Variant::Argon2d));
+ assert_eq!(Variant::from_str("argon2i"), Ok(Variant::Argon2i));
+ assert_eq!(Variant::from_str("argon2id"), Ok(Variant::Argon2id));
+ assert_eq!(Variant::from_str("foobar"), Err(Error::DecodingFail));
+ }
+
+ #[test]
+ fn from_u32_returns_correct_result() {
+ assert_eq!(Variant::from_u32(0), Ok(Variant::Argon2d));
+ assert_eq!(Variant::from_u32(1), Ok(Variant::Argon2i));
+ assert_eq!(Variant::from_u32(2), Ok(Variant::Argon2id));
+ assert_eq!(Variant::from_u32(3), Err(Error::IncorrectType));
+ }
+}
diff --git a/third_party/rust/rust-argon2/src/version.rs b/third_party/rust/rust-argon2/src/version.rs
new file mode 100644
index 0000000000..b8c03ba918
--- /dev/null
+++ b/third_party/rust/rust-argon2/src/version.rs
@@ -0,0 +1,97 @@
+// Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com>
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::fmt;
+use super::error::Error;
+use super::result::Result;
+
+/// The Argon2 version.
+#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
+pub enum Version {
+ /// Version 0x10.
+ Version10 = 0x10,
+
+ /// Version 0x13 (Recommended).
+ Version13 = 0x13,
+}
+
+impl Version {
+ /// Gets the u32 representation of the version.
+ pub fn as_u32(&self) -> u32 {
+ *self as u32
+ }
+
+ /// Attempts to create a version from a string slice.
+ pub fn from_str(str: &str) -> Result<Version> {
+ match str {
+ "16" => Ok(Version::Version10),
+ "19" => Ok(Version::Version13),
+ _ => Err(Error::DecodingFail),
+ }
+ }
+
+ /// Attempts to create a version from an u32.
+ pub fn from_u32(val: u32) -> Result<Version> {
+ match val {
+ 0x10 => Ok(Version::Version10),
+ 0x13 => Ok(Version::Version13),
+ _ => Err(Error::IncorrectVersion),
+ }
+ }
+}
+
+impl Default for Version {
+ fn default() -> Version {
+ Version::Version13
+ }
+}
+
+impl fmt::Display for Version {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.as_u32())
+ }
+}
+
+
+#[cfg(test)]
+mod tests {
+
+ use error::Error;
+ use super::*;
+
+ #[test]
+ fn as_u32_returns_correct_u32() {
+ assert_eq!(Version::Version10.as_u32(), 0x10);
+ assert_eq!(Version::Version13.as_u32(), 0x13);
+ }
+
+ #[test]
+ fn default_returns_correct_version() {
+ assert_eq!(Version::default(), Version::Version13);
+ }
+
+ #[test]
+ fn display_returns_correct_string() {
+ assert_eq!(format!("{}", Version::Version10), "16");
+ assert_eq!(format!("{}", Version::Version13), "19");
+ }
+
+ #[test]
+ fn from_str_returns_correct_result() {
+ assert_eq!(Version::from_str("16"), Ok(Version::Version10));
+ assert_eq!(Version::from_str("19"), Ok(Version::Version13));
+ assert_eq!(Version::from_str("11"), Err(Error::DecodingFail));
+ }
+
+ #[test]
+ fn from_u32_returns_correct_result() {
+ assert_eq!(Version::from_u32(0x10), Ok(Version::Version10));
+ assert_eq!(Version::from_u32(0x13), Ok(Version::Version13));
+ assert_eq!(Version::from_u32(0), Err(Error::IncorrectVersion));
+ }
+}
diff --git a/third_party/rust/rust-argon2/tests/integration_test.rs b/third_party/rust/rust-argon2/tests/integration_test.rs
new file mode 100644
index 0000000000..c2e07c78f4
--- /dev/null
+++ b/third_party/rust/rust-argon2/tests/integration_test.rs
@@ -0,0 +1,1076 @@
+// Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com>
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// These tests are based on Argon's test.c test suite.
+
+extern crate argon2;
+extern crate hex;
+
+use argon2::{Error, Config, ThreadMode, Variant, Version};
+use hex::ToHex;
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2d_version10_1() {
+ hash_test(
+ Variant::Argon2d,
+ Version::Version10,
+ 2,
+ 65536,
+ 1,
+ b"password",
+ b"somesalt",
+ "2ec0d925358f5830caf0c1cc8a3ee58b34505759428b859c79b72415f51f9221",
+ "$argon2d$m=65536,t=2,p=1$c29tZXNhbHQ\
+ $LsDZJTWPWDDK8MHMij7lizRQV1lCi4WcebckFfUfkiE",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2d_version10_2() {
+ hash_test(
+ Variant::Argon2d,
+ Version::Version10,
+ 2,
+ 1048576,
+ 1,
+ b"password",
+ b"somesalt",
+ "28ae0d1037991b55faec18425274d5f9169b2f44bee19b45b7a561d489d6019a",
+ "$argon2d$m=1048576,t=2,p=1$c29tZXNhbHQ\
+ $KK4NEDeZG1X67BhCUnTV+RabL0S+4ZtFt6Vh1InWAZo",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2d_version10_3() {
+ hash_test(
+ Variant::Argon2d,
+ Version::Version10,
+ 2,
+ 262144,
+ 1,
+ b"password",
+ b"somesalt",
+ "41c89760d85b80ba1be7e959ebd16390bfb4176db9466d70f670457ccade4ec8",
+ "$argon2d$m=262144,t=2,p=1$c29tZXNhbHQ\
+ $QciXYNhbgLob5+lZ69FjkL+0F225Rm1w9nBFfMreTsg",
+ );
+}
+
+#[test]
+fn test_argon2d_version10_4() {
+ hash_test(
+ Variant::Argon2d,
+ Version::Version10,
+ 2,
+ 256,
+ 1,
+ b"password",
+ b"somesalt",
+ "bd404868ff00c52e7543c8332e6a772a5724892d7e328d5cf253bbc8e726b371",
+ "$argon2d$m=256,t=2,p=1$c29tZXNhbHQ\
+ $vUBIaP8AxS51Q8gzLmp3KlckiS1+Mo1c8lO7yOcms3E",
+ );
+}
+
+#[test]
+fn test_argon2d_version10_5() {
+ hash_test(
+ Variant::Argon2d,
+ Version::Version10,
+ 2,
+ 256,
+ 2,
+ b"password",
+ b"somesalt",
+ "6a91d02b9f8854ba0841f04aa6e53c1d3374c0a0c646b8e431b03de805b91ec3",
+ "$argon2d$m=256,t=2,p=2$c29tZXNhbHQ\
+ $apHQK5+IVLoIQfBKpuU8HTN0wKDGRrjkMbA96AW5HsM",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2d_version10_6() {
+ hash_test(
+ Variant::Argon2d,
+ Version::Version10,
+ 1,
+ 65536,
+ 1,
+ b"password",
+ b"somesalt",
+ "05d1d0a85f499e9397b9c1c936b20f366a7273ccf259e2edfdb44ca8f86dd11f",
+ "$argon2d$m=65536,t=1,p=1$c29tZXNhbHQ\
+ $BdHQqF9JnpOXucHJNrIPNmpyc8zyWeLt/bRMqPht0R8",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2d_version10_7() {
+ hash_test(
+ Variant::Argon2d,
+ Version::Version10,
+ 4,
+ 65536,
+ 1,
+ b"password",
+ b"somesalt",
+ "99e787faced20949df5a3b9c8620712b45cfea061716adf8b13efb7feee44084",
+ "$argon2d$m=65536,t=4,p=1$c29tZXNhbHQ\
+ $meeH+s7SCUnfWjuchiBxK0XP6gYXFq34sT77f+7kQIQ",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2d_version10_8() {
+ hash_test(
+ Variant::Argon2d,
+ Version::Version10,
+ 2,
+ 65536,
+ 1,
+ b"differentpassword",
+ b"somesalt",
+ "b9c2e4a4ec9a6db99ca4e2b549dd64256305b95754b0a70ad757cd1ff7eed4a4",
+ "$argon2d$m=65536,t=2,p=1$c29tZXNhbHQ\
+ $ucLkpOyabbmcpOK1Sd1kJWMFuVdUsKcK11fNH/fu1KQ",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2d_version10_9() {
+ hash_test(
+ Variant::Argon2d,
+ Version::Version10,
+ 2,
+ 65536,
+ 1,
+ b"password",
+ b"diffsalt",
+ "d1da14196c233e0a3cb687aa6e6c465cb50669ffdb891158c2b75722395f14d5",
+ "$argon2d$m=65536,t=2,p=1$ZGlmZnNhbHQ\
+ $0doUGWwjPgo8toeqbmxGXLUGaf/biRFYwrdXIjlfFNU",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2d_version13_1() {
+ hash_test(
+ Variant::Argon2d,
+ Version::Version13,
+ 2,
+ 65536,
+ 1,
+ b"password",
+ b"somesalt",
+ "955e5d5b163a1b60bba35fc36d0496474fba4f6b59ad53628666f07fb2f93eaf",
+ "$argon2d$v=19$m=65536,t=2,p=1$c29tZXNhbHQ\
+ $lV5dWxY6G2C7o1/DbQSWR0+6T2tZrVNihmbwf7L5Pq8",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2d_version13_2() {
+ hash_test(
+ Variant::Argon2d,
+ Version::Version13,
+ 2,
+ 1048576,
+ 1,
+ b"password",
+ b"somesalt",
+ "c2d680a6e7ac1b75e2c2b1e5e71b1701584869492efea4a76ccc91fec622d1ae",
+ "$argon2d$v=19$m=1048576,t=2,p=1$c29tZXNhbHQ\
+ $wtaApuesG3XiwrHl5xsXAVhIaUku/qSnbMyR/sYi0a4",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2d_version13_3() {
+ hash_test(
+ Variant::Argon2d,
+ Version::Version13,
+ 2,
+ 262144,
+ 1,
+ b"password",
+ b"somesalt",
+ "9678b3379ce20ddc96fa38f045c8cdc96282287ff2848efd867582b9528a2155",
+ "$argon2d$v=19$m=262144,t=2,p=1$c29tZXNhbHQ\
+ $lnizN5ziDdyW+jjwRcjNyWKCKH/yhI79hnWCuVKKIVU",
+ );
+}
+
+#[test]
+fn test_argon2d_version13_4() {
+ hash_test(
+ Variant::Argon2d,
+ Version::Version13,
+ 2,
+ 256,
+ 1,
+ b"password",
+ b"somesalt",
+ "25c4ee8ba448054b49efc804e478b9d823be1f9bd2e99f51d6ec4007a3a1501f",
+ "$argon2d$v=19$m=256,t=2,p=1$c29tZXNhbHQ\
+ $JcTui6RIBUtJ78gE5Hi52CO+H5vS6Z9R1uxAB6OhUB8",
+ );
+}
+
+#[test]
+fn test_argon2d_version13_5() {
+ hash_test(
+ Variant::Argon2d,
+ Version::Version13,
+ 2,
+ 256,
+ 2,
+ b"password",
+ b"somesalt",
+ "7b69c92d7c3889aad1281dbc8baefc12cc37c80f1c75e33ef2c2d40c28ebc573",
+ "$argon2d$v=19$m=256,t=2,p=2$c29tZXNhbHQ\
+ $e2nJLXw4iarRKB28i678Esw3yA8cdeM+8sLUDCjrxXM",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2d_version13_6() {
+ hash_test(
+ Variant::Argon2d,
+ Version::Version13,
+ 1,
+ 65536,
+ 1,
+ b"password",
+ b"somesalt",
+ "8193708c030f09b121526b0efdffce738fef0ddb13937a65d43f3f1eab9aa802",
+ "$argon2d$v=19$m=65536,t=1,p=1$c29tZXNhbHQ\
+ $gZNwjAMPCbEhUmsO/f/Oc4/vDdsTk3pl1D8/HquaqAI",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2d_version13_7() {
+ hash_test(
+ Variant::Argon2d,
+ Version::Version13,
+ 4,
+ 65536,
+ 1,
+ b"password",
+ b"somesalt",
+ "cd1e2816cf8895fffe535b87b7a0aa3612f73c6ce063de83b1e7b4621ca0afe6",
+ "$argon2d$v=19$m=65536,t=4,p=1$c29tZXNhbHQ\
+ $zR4oFs+Ilf/+U1uHt6CqNhL3PGzgY96Dsee0Yhygr+Y",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2d_version13_8() {
+ hash_test(
+ Variant::Argon2d,
+ Version::Version13,
+ 2,
+ 65536,
+ 1,
+ b"differentpassword",
+ b"somesalt",
+ "a34dafc893182d521ae467bbfdce60f973a1223c4615654efeb0bfef8a930e25",
+ "$argon2d$v=19$m=65536,t=2,p=1$c29tZXNhbHQ\
+ $o02vyJMYLVIa5Ge7/c5g+XOhIjxGFWVO/rC/74qTDiU",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2d_version13_9() {
+ hash_test(
+ Variant::Argon2d,
+ Version::Version13,
+ 2,
+ 65536,
+ 1,
+ b"password",
+ b"diffsalt",
+ "f00eb8a999a1c6949c61fbbee3c3cece5066e3ff5c79aed421266055e2bf4dd7",
+ "$argon2d$v=19$m=65536,t=2,p=1$ZGlmZnNhbHQ\
+ $8A64qZmhxpScYfu+48POzlBm4/9cea7UISZgVeK/Tdc",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2i_version10_1() {
+ hash_test(
+ Variant::Argon2i,
+ Version::Version10,
+ 2,
+ 65536,
+ 1,
+ b"password",
+ b"somesalt",
+ "f6c4db4a54e2a370627aff3db6176b94a2a209a62c8e36152711802f7b30c694",
+ "$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ\
+ $9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2i_version10_2() {
+ hash_test(
+ Variant::Argon2i,
+ Version::Version10,
+ 2,
+ 1048576,
+ 1,
+ b"password",
+ b"somesalt",
+ "9690ec55d28d3ed32562f2e73ea62b02b018757643a2ae6e79528459de8106e9",
+ "$argon2i$m=1048576,t=2,p=1$c29tZXNhbHQ\
+ $lpDsVdKNPtMlYvLnPqYrArAYdXZDoq5ueVKEWd6BBuk",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2i_version10_3() {
+ hash_test(
+ Variant::Argon2i,
+ Version::Version10,
+ 2,
+ 262144,
+ 1,
+ b"password",
+ b"somesalt",
+ "3e689aaa3d28a77cf2bc72a51ac53166761751182f1ee292e3f677a7da4c2467",
+ "$argon2i$m=262144,t=2,p=1$c29tZXNhbHQ\
+ $Pmiaqj0op3zyvHKlGsUxZnYXURgvHuKS4/Z3p9pMJGc",
+ );
+}
+
+#[test]
+fn test_argon2i_version10_4() {
+ hash_test(
+ Variant::Argon2i,
+ Version::Version10,
+ 2,
+ 256,
+ 1,
+ b"password",
+ b"somesalt",
+ "fd4dd83d762c49bdeaf57c47bdcd0c2f1babf863fdeb490df63ede9975fccf06",
+ "$argon2i$m=256,t=2,p=1$c29tZXNhbHQ\
+ $/U3YPXYsSb3q9XxHvc0MLxur+GP960kN9j7emXX8zwY",
+ );
+}
+
+#[test]
+fn test_argon2i_version10_5() {
+ hash_test(
+ Variant::Argon2i,
+ Version::Version10,
+ 2,
+ 256,
+ 2,
+ b"password",
+ b"somesalt",
+ "b6c11560a6a9d61eac706b79a2f97d68b4463aa3ad87e00c07e2b01e90c564fb",
+ "$argon2i$m=256,t=2,p=2$c29tZXNhbHQ\
+ $tsEVYKap1h6scGt5ovl9aLRGOqOth+AMB+KwHpDFZPs",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2i_version10_6() {
+ hash_test(
+ Variant::Argon2i,
+ Version::Version10,
+ 1,
+ 65536,
+ 1,
+ b"password",
+ b"somesalt",
+ "81630552b8f3b1f48cdb1992c4c678643d490b2b5eb4ff6c4b3438b5621724b2",
+ "$argon2i$m=65536,t=1,p=1$c29tZXNhbHQ\
+ $gWMFUrjzsfSM2xmSxMZ4ZD1JCytetP9sSzQ4tWIXJLI",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2i_version10_7() {
+ hash_test(
+ Variant::Argon2i,
+ Version::Version10,
+ 4,
+ 65536,
+ 1,
+ b"password",
+ b"somesalt",
+ "f212f01615e6eb5d74734dc3ef40ade2d51d052468d8c69440a3a1f2c1c2847b",
+ "$argon2i$m=65536,t=4,p=1$c29tZXNhbHQ\
+ $8hLwFhXm6110c03D70Ct4tUdBSRo2MaUQKOh8sHChHs",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2i_version10_8() {
+ hash_test(
+ Variant::Argon2i,
+ Version::Version10,
+ 2,
+ 65536,
+ 1,
+ b"differentpassword",
+ b"somesalt",
+ "e9c902074b6754531a3a0be519e5baf404b30ce69b3f01ac3bf21229960109a3",
+ "$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ\
+ $6ckCB0tnVFMaOgvlGeW69ASzDOabPwGsO/ISKZYBCaM",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2i_version10_9() {
+ hash_test(
+ Variant::Argon2i,
+ Version::Version10,
+ 2,
+ 65536,
+ 1,
+ b"password",
+ b"diffsalt",
+ "79a103b90fe8aef8570cb31fc8b22259778916f8336b7bdac3892569d4f1c497",
+ "$argon2i$m=65536,t=2,p=1$ZGlmZnNhbHQ\
+ $eaEDuQ/orvhXDLMfyLIiWXeJFvgza3vaw4kladTxxJc",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2i_version13_1() {
+ hash_test(
+ Variant::Argon2i,
+ Version::Version13,
+ 2,
+ 65536,
+ 1,
+ b"password",
+ b"somesalt",
+ "c1628832147d9720c5bd1cfd61367078729f6dfb6f8fea9ff98158e0d7816ed0",
+ "$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ\
+ $wWKIMhR9lyDFvRz9YTZweHKfbftvj+qf+YFY4NeBbtA",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2i_version13_2() {
+ hash_test(
+ Variant::Argon2i,
+ Version::Version13,
+ 2,
+ 1048576,
+ 1,
+ b"password",
+ b"somesalt",
+ "d1587aca0922c3b5d6a83edab31bee3c4ebaef342ed6127a55d19b2351ad1f41",
+ "$argon2i$v=19$m=1048576,t=2,p=1$c29tZXNhbHQ\
+ $0Vh6ygkiw7XWqD7asxvuPE667zQu1hJ6VdGbI1GtH0E",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2i_version13_3() {
+ hash_test(
+ Variant::Argon2i,
+ Version::Version13,
+ 2,
+ 262144,
+ 1,
+ b"password",
+ b"somesalt",
+ "296dbae80b807cdceaad44ae741b506f14db0959267b183b118f9b24229bc7cb",
+ "$argon2i$v=19$m=262144,t=2,p=1$c29tZXNhbHQ\
+ $KW266AuAfNzqrUSudBtQbxTbCVkmexg7EY+bJCKbx8s",
+ );
+}
+
+#[test]
+fn test_argon2i_version13_4() {
+ hash_test(
+ Variant::Argon2i,
+ Version::Version13,
+ 2,
+ 256,
+ 1,
+ b"password",
+ b"somesalt",
+ "89e9029f4637b295beb027056a7336c414fadd43f6b208645281cb214a56452f",
+ "$argon2i$v=19$m=256,t=2,p=1$c29tZXNhbHQ\
+ $iekCn0Y3spW+sCcFanM2xBT63UP2sghkUoHLIUpWRS8",
+ );
+}
+
+#[test]
+fn test_argon2i_version13_5() {
+ hash_test(
+ Variant::Argon2i,
+ Version::Version13,
+ 2,
+ 256,
+ 2,
+ b"password",
+ b"somesalt",
+ "4ff5ce2769a1d7f4c8a491df09d41a9fbe90e5eb02155a13e4c01e20cd4eab61",
+ "$argon2i$v=19$m=256,t=2,p=2$c29tZXNhbHQ\
+ $T/XOJ2mh1/TIpJHfCdQan76Q5esCFVoT5MAeIM1Oq2E",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2i_version13_6() {
+ hash_test(
+ Variant::Argon2i,
+ Version::Version13,
+ 1,
+ 65536,
+ 1,
+ b"password",
+ b"somesalt",
+ "d168075c4d985e13ebeae560cf8b94c3b5d8a16c51916b6f4ac2da3ac11bbecf",
+ "$argon2i$v=19$m=65536,t=1,p=1$c29tZXNhbHQ\
+ $0WgHXE2YXhPr6uVgz4uUw7XYoWxRkWtvSsLaOsEbvs8",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2i_version13_7() {
+ hash_test(
+ Variant::Argon2i,
+ Version::Version13,
+ 4,
+ 65536,
+ 1,
+ b"password",
+ b"somesalt",
+ "aaa953d58af3706ce3df1aefd4a64a84e31d7f54175231f1285259f88174ce5b",
+ "$argon2i$v=19$m=65536,t=4,p=1$c29tZXNhbHQ\
+ $qqlT1YrzcGzj3xrv1KZKhOMdf1QXUjHxKFJZ+IF0zls",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2i_version13_8() {
+ hash_test(
+ Variant::Argon2i,
+ Version::Version13,
+ 2,
+ 65536,
+ 1,
+ b"differentpassword",
+ b"somesalt",
+ "14ae8da01afea8700c2358dcef7c5358d9021282bd88663a4562f59fb74d22ee",
+ "$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ\
+ $FK6NoBr+qHAMI1jc73xTWNkCEoK9iGY6RWL1n7dNIu4",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2i_version13_9() {
+ hash_test(
+ Variant::Argon2i,
+ Version::Version13,
+ 2,
+ 65536,
+ 1,
+ b"password",
+ b"diffsalt",
+ "b0357cccfbef91f3860b0dba447b2348cbefecadaf990abfe9cc40726c521271",
+ "$argon2i$v=19$m=65536,t=2,p=1$ZGlmZnNhbHQ\
+ $sDV8zPvvkfOGCw26RHsjSMvv7K2vmQq/6cxAcmxSEnE",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2id_version10_1() {
+ hash_test(
+ Variant::Argon2id,
+ Version::Version10,
+ 2,
+ 65536,
+ 1,
+ b"password",
+ b"somesalt",
+ "980ebd24a4e667f16346f9d4a78b175728783613e0cc6fb17c2ec884b16435df",
+ "$argon2id$v=16$m=65536,t=2,p=1$c29tZXNhbHQ\
+ $mA69JKTmZ/FjRvnUp4sXVyh4NhPgzG+xfC7IhLFkNd8",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2id_version10_2() {
+ hash_test(
+ Variant::Argon2id,
+ Version::Version10,
+ 2,
+ 1048576,
+ 1,
+ b"password",
+ b"somesalt",
+ "ce622fc2053acd224c06e7be122f9e9554b62b8a414b032056b46123422e32ab",
+ "$argon2id$v=16$m=1048576,t=2,p=1$c29tZXNhbHQ\
+ $zmIvwgU6zSJMBue+Ei+elVS2K4pBSwMgVrRhI0IuMqs",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2id_version10_3() {
+ hash_test(
+ Variant::Argon2id,
+ Version::Version10,
+ 2,
+ 262144,
+ 1,
+ b"password",
+ b"somesalt",
+ "01cbafb58f2dc764adced1ab9a90fcb62f6ed8a066023b6ba0c204db6c9b90cd",
+ "$argon2id$v=16$m=262144,t=2,p=1$c29tZXNhbHQ\
+ $AcuvtY8tx2StztGrmpD8ti9u2KBmAjtroMIE22ybkM0",
+ );
+}
+
+#[test]
+fn test_argon2id_version10_4() {
+ hash_test(
+ Variant::Argon2id,
+ Version::Version10,
+ 2,
+ 256,
+ 1,
+ b"password",
+ b"somesalt",
+ "da070e576e50f2f38a3c897cbddc6c7fb4028e870971ff9eae7b4e1879295e6e",
+ "$argon2id$v=16$m=256,t=2,p=1$c29tZXNhbHQ\
+ $2gcOV25Q8vOKPIl8vdxsf7QCjocJcf+erntOGHkpXm4",
+ );
+}
+
+#[test]
+fn test_argon2id_version10_5() {
+ hash_test(
+ Variant::Argon2id,
+ Version::Version10,
+ 2,
+ 256,
+ 2,
+ b"password",
+ b"somesalt",
+ "f8aabb5315c63cddcdb3b4a021550928e525699da8fcbd1c2b0b1ccd35cc87a7",
+ "$argon2id$v=16$m=256,t=2,p=2$c29tZXNhbHQ\
+ $+Kq7UxXGPN3Ns7SgIVUJKOUlaZ2o/L0cKwsczTXMh6c",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2id_version10_6() {
+ hash_test(
+ Variant::Argon2id,
+ Version::Version10,
+ 1,
+ 65536,
+ 1,
+ b"password",
+ b"somesalt",
+ "8e0f310407a989013a823defbd6cbae54d86b35d1ac16e4f88eb4645e1357956",
+ "$argon2id$v=16$m=65536,t=1,p=1$c29tZXNhbHQ\
+ $jg8xBAepiQE6gj3vvWy65U2Gs10awW5PiOtGReE1eVY",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2id_version10_7() {
+ hash_test(
+ Variant::Argon2id,
+ Version::Version10,
+ 4,
+ 65536,
+ 1,
+ b"password",
+ b"somesalt",
+ "16653426e582143da6a0ff75daac9fa94c21ac2c221c96bd3645a5c15c2d962a",
+ "$argon2id$v=16$m=65536,t=4,p=1$c29tZXNhbHQ\
+ $FmU0JuWCFD2moP912qyfqUwhrCwiHJa9NkWlwVwtlio",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2id_version10_8() {
+ hash_test(
+ Variant::Argon2id,
+ Version::Version10,
+ 2,
+ 65536,
+ 1,
+ b"differentpassword",
+ b"somesalt",
+ "75709d4c96a2c235696a77eefeecf33e64221f470b26177c19e5e27642612dbb",
+ "$argon2id$v=16$m=65536,t=2,p=1$c29tZXNhbHQ\
+ $dXCdTJaiwjVpanfu/uzzPmQiH0cLJhd8GeXidkJhLbs",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2id_version10_9() {
+ hash_test(
+ Variant::Argon2id,
+ Version::Version10,
+ 2,
+ 65536,
+ 1,
+ b"password",
+ b"diffsalt",
+ "f0b57cfe03a9d78c4700e2fe802002343660a56b1b5d21ead788e6bb44ef48d3",
+ "$argon2id$v=16$m=65536,t=2,p=1$ZGlmZnNhbHQ\
+ $8LV8/gOp14xHAOL+gCACNDZgpWsbXSHq14jmu0TvSNM",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2id_version13_1() {
+ hash_test(
+ Variant::Argon2id,
+ Version::Version13,
+ 2,
+ 65536,
+ 1,
+ b"password",
+ b"somesalt",
+ "09316115d5cf24ed5a15a31a3ba326e5cf32edc24702987c02b6566f61913cf7",
+ "$argon2id$v=19$m=65536,t=2,p=1$c29tZXNhbHQ\
+ $CTFhFdXPJO1aFaMaO6Mm5c8y7cJHAph8ArZWb2GRPPc",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2id_version13_2() {
+ hash_test(
+ Variant::Argon2id,
+ Version::Version13,
+ 2,
+ 1048576,
+ 1,
+ b"password",
+ b"somesalt",
+ "16a1cb8a061cf1f8b16fb195fe559fa6d1435e43dded2f4fb07293176be892fa",
+ "$argon2id$v=19$m=1048576,t=2,p=1$c29tZXNhbHQ\
+ $FqHLigYc8fixb7GV/lWfptFDXkPd7S9PsHKTF2vokvo",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2id_version13_3() {
+ hash_test(
+ Variant::Argon2id,
+ Version::Version13,
+ 2,
+ 262144,
+ 1,
+ b"password",
+ b"somesalt",
+ "78fe1ec91fb3aa5657d72e710854e4c3d9b9198c742f9616c2f085bed95b2e8c",
+ "$argon2id$v=19$m=262144,t=2,p=1$c29tZXNhbHQ\
+ $eP4eyR+zqlZX1y5xCFTkw9m5GYx0L5YWwvCFvtlbLow",
+ );
+}
+
+#[test]
+fn test_argon2id_version13_4() {
+ hash_test(
+ Variant::Argon2id,
+ Version::Version13,
+ 2,
+ 256,
+ 1,
+ b"password",
+ b"somesalt",
+ "9dfeb910e80bad0311fee20f9c0e2b12c17987b4cac90c2ef54d5b3021c68bfe",
+ "$argon2id$v=19$m=256,t=2,p=1$c29tZXNhbHQ\
+ $nf65EOgLrQMR/uIPnA4rEsF5h7TKyQwu9U1bMCHGi/4",
+ );
+}
+
+#[test]
+fn test_argon2id_version13_5() {
+ hash_test(
+ Variant::Argon2id,
+ Version::Version13,
+ 2,
+ 256,
+ 2,
+ b"password",
+ b"somesalt",
+ "6d093c501fd5999645e0ea3bf620d7b8be7fd2db59c20d9fff9539da2bf57037",
+ "$argon2id$v=19$m=256,t=2,p=2$c29tZXNhbHQ\
+ $bQk8UB/VmZZF4Oo79iDXuL5/0ttZwg2f/5U52iv1cDc",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2id_version13_6() {
+ hash_test(
+ Variant::Argon2id,
+ Version::Version13,
+ 1,
+ 65536,
+ 1,
+ b"password",
+ b"somesalt",
+ "f6a5adc1ba723dddef9b5ac1d464e180fcd9dffc9d1cbf76cca2fed795d9ca98",
+ "$argon2id$v=19$m=65536,t=1,p=1$c29tZXNhbHQ\
+ $9qWtwbpyPd3vm1rB1GThgPzZ3/ydHL92zKL+15XZypg",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2id_version13_7() {
+ hash_test(
+ Variant::Argon2id,
+ Version::Version13,
+ 4,
+ 65536,
+ 1,
+ b"password",
+ b"somesalt",
+ "9025d48e68ef7395cca9079da4c4ec3affb3c8911fe4f86d1a2520856f63172c",
+ "$argon2id$v=19$m=65536,t=4,p=1$c29tZXNhbHQ\
+ $kCXUjmjvc5XMqQedpMTsOv+zyJEf5PhtGiUghW9jFyw",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2id_version13_8() {
+ hash_test(
+ Variant::Argon2id,
+ Version::Version13,
+ 2,
+ 65536,
+ 1,
+ b"differentpassword",
+ b"somesalt",
+ "0b84d652cf6b0c4beaef0dfe278ba6a80df6696281d7e0d2891b817d8c458fde",
+ "$argon2id$v=19$m=65536,t=2,p=1$c29tZXNhbHQ\
+ $C4TWUs9rDEvq7w3+J4umqA32aWKB1+DSiRuBfYxFj94",
+ );
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_argon2id_version13_9() {
+ hash_test(
+ Variant::Argon2id,
+ Version::Version13,
+ 2,
+ 65536,
+ 1,
+ b"password",
+ b"diffsalt",
+ "bdf32b05ccc42eb15d58fd19b1f856b113da1e9a5874fdcc544308565aa8141c",
+ "$argon2id$v=19$m=65536,t=2,p=1$ZGlmZnNhbHQ\
+ $vfMrBczELrFdWP0ZsfhWsRPaHppYdP3MVEMIVlqoFBw",
+ );
+}
+
+#[test]
+fn test_verify_encoded_with_missing_dollar_before_salt_version10() {
+ let encoded = "$argon2i$m=65536,t=2,p=1c29tZXNhbHQ\
+ $9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ";
+ let password = b"password";
+ let res = argon2::verify_encoded(encoded, password);
+ assert_eq!(res, Err(Error::DecodingFail));
+}
+
+#[test]
+fn test_verify_encoded_with_missing_dollar_before_salt_version13() {
+ let encoded = "$argon2i$v=19$m=65536,t=2,p=1c29tZXNhbHQ\
+ $wWKIMhR9lyDFvRz9YTZweHKfbftvj+qf+YFY4NeBbtA";
+ let password = b"password";
+ let res = argon2::verify_encoded(encoded, password);
+ assert_eq!(res, Err(Error::DecodingFail));
+}
+
+#[test]
+fn test_verify_encoded_with_missing_dollar_before_hash_version10() {
+ let encoded = "$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ\
+ 9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ";
+ let password = b"password";
+ let res = argon2::verify_encoded(encoded, password);
+ assert_eq!(res, Err(Error::DecodingFail));
+}
+
+#[test]
+fn test_verify_encoded_with_missing_dollar_before_hash_version13() {
+ let encoded = "$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ\
+ wWKIMhR9lyDFvRz9YTZweHKfbftvj+qf+YFY4NeBbtA";
+ let password = b"password";
+ let res = argon2::verify_encoded(encoded, password);
+ assert_eq!(res, Err(Error::DecodingFail));
+}
+
+#[test]
+fn test_verify_encoded_with_too_short_salt_version10() {
+ let encoded = "$argon2i$m=65536,t=2,p=1$\
+ $9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ";
+ let password = b"password";
+ let res = argon2::verify_encoded(encoded, password);
+ assert_eq!(res, Err(Error::SaltTooShort));
+}
+
+#[test]
+fn test_verify_encoded_with_too_short_salt_version13() {
+ let encoded = "$argon2i$v=19$m=65536,t=2,p=1$\
+ $9sTbSlTio3Biev89thdrlKKiCaYsjjYVJxGAL3swxpQ";
+ let password = b"password";
+ let res = argon2::verify_encoded(encoded, password);
+ assert_eq!(res, Err(Error::SaltTooShort));
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_verify_encoded_with_wrong_password_version10() {
+ let encoded = "$argon2i$m=65536,t=2,p=1$c29tZXNhbHQ\
+ $b2G3seW+uPzerwQQC+/E1K50CLLO7YXy0JRcaTuswRo";
+ let password = b"password"; // should be passwore
+ let res = argon2::verify_encoded(encoded, password);
+ assert_eq!(res, Ok(false));
+}
+
+#[cfg(not(debug_assertions))]
+#[test]
+fn test_verify_encoded_with_wrong_password_version13() {
+ let encoded = "$argon2i$v=19$m=65536,t=2,p=1$c29tZXNhbHQ\
+ $8iIuixkI73Js3G1uMbezQXD0b8LG4SXGsOwoQkdAQIM";
+ let password = b"password"; // should be passwore
+ let res = argon2::verify_encoded(encoded, password);
+ assert_eq!(res, Ok(false));
+}
+
+#[test]
+fn test_encoded_len_returns_correct_length() {
+ assert_eq!(argon2::encoded_len(Variant::Argon2d, 256, 1, 1, 8, 32), 83);
+ assert_eq!(argon2::encoded_len(Variant::Argon2i, 4096, 10, 10, 8, 32), 86);
+ assert_eq!(argon2::encoded_len(Variant::Argon2id, 65536, 100, 10, 8, 32), 89);
+}
+
+#[test]
+fn test_hash_raw_with_not_enough_memory() {
+ let pwd = b"password";
+ let salt = b"diffsalt";
+ let config = Config {
+ variant: Variant::Argon2i,
+ version: Version::Version13,
+ mem_cost: 2,
+ time_cost: 2,
+ lanes: 1,
+ thread_mode: ThreadMode::Sequential,
+ secret: &[],
+ ad: &[],
+ hash_length: 32,
+ };
+ let res = argon2::hash_raw(pwd, salt, &config);
+ assert_eq!(res, Err(Error::MemoryTooLittle));
+}
+
+#[test]
+fn test_hash_raw_with_too_short_salt() {
+ let pwd = b"password";
+ let salt = b"s";
+ let config = Config {
+ variant: Variant::Argon2i,
+ version: Version::Version13,
+ mem_cost: 2048,
+ time_cost: 2,
+ lanes: 1,
+ thread_mode: ThreadMode::Sequential,
+ secret: &[],
+ ad: &[],
+ hash_length: 32,
+ };
+ let res = argon2::hash_raw(pwd, salt, &config);
+ assert_eq!(res, Err(Error::SaltTooShort));
+}
+
+fn hash_test(
+ var: Variant,
+ ver: Version,
+ t: u32,
+ m: u32,
+ p: u32,
+ pwd: &[u8],
+ salt: &[u8],
+ hex: &str,
+ enc: &str,
+) {
+ let config = Config {
+ variant: var,
+ version: ver,
+ mem_cost: m,
+ time_cost: t,
+ lanes: p,
+ thread_mode: ThreadMode::from_threads(p),
+ secret: &[],
+ ad: &[],
+ hash_length: 32,
+ };
+ let hash = argon2::hash_raw(pwd, salt, &config).unwrap();
+ let mut hex_str = String::new();
+ let res = hash.write_hex(&mut hex_str);
+ assert_eq!(res, Ok(()));
+ assert_eq!(hex_str.as_str(), hex);
+
+ let encoded = argon2::hash_encoded(pwd, salt, &config).unwrap();
+ let result = argon2::verify_encoded(encoded.as_str(), pwd).unwrap();
+ assert!(result);
+
+ let result = argon2::verify_encoded(enc, pwd).unwrap();
+ assert!(result);
+}