1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
//! [![Build Status](https://travis-ci.org/bcmyers/argonautica.svg?branch=master)](https://travis-ci.org/bcmyers/argonautica)
//! [![Crates.io](https://img.shields.io/crates/v/argonautica.svg)](https://crates.io/crates/argonautica)
//! [![Documentation](https://docs.rs/argonautica/badge.svg)](https://docs.rs/argonautica/)
//! [![Github.com](https://img.shields.io/badge/github-bcmyers%2Fargonautica-blue.svg)](http://www.github.com/bcmyers/argonautica)
//! ![License](https://img.shields.io/crates/l/argonautica.svg)
//!
//! # Overview
//!
//! <b>argonautica</b> is a Rust crate for hashing passwords using the cryptographically-secure
//! [Argon2 hashing algorithm](https://tools.ietf.org/html/draft-irtf-cfrg-argon2-03).
//!
//! [Argon2]((https://tools.ietf.org/html/draft-irtf-cfrg-argon2-03)) won the
//! [Password Hashing Competition](https://password-hashing.net/) in 2015, a several
//! year project to identify a successor to [bcrypt](https://en.wikipedia.org/wiki/Bcrypt),
//! [scrypt](https://en.wikipedia.org/wiki/Scrypt), and other common cryptographically-secure
//! hashing algorithms.
//!
//! The <b>argonautica</b> crate was designed:
//! * to be easy to use,
//! * to have robust, beginner-friendly documentation, and
//! * to (as much as possible) follow the
//!   [Rust API guidelines](https://rust-lang-nursery.github.io/api-guidelines/)
//!
//! <b>argonautica</b> was built with a simple use-case in mind: hashing passwords for storage in a
//! website's database. That said, it's also "feature-complete", meaning anything you can do with
//! the cannonical [C implementation](https://github.com/P-H-C/phc-winner-argon2) of Argon2
//! you can do with argonautica*.
//!
//! <i>\* Indeed, argonautica has a feature that even the cannonical C implementation
//! lacks, i.e. hashing passwords with secret keys (the C implementation implements this, but
//! does not expose it publicly)</i>
//!
//! # Hashing
//!
//! Hashing passwords with <b>argonautica</b> is simple.  Just instantiate a default
//! [`Hasher`](struct.Hasher.html), provide it with a password and a secret key, and then
//! call the [`hash`](struct.Hasher.html#method.hash) method.
//! ```
//! extern crate argonautica;
//!
//! use argonautica::Hasher;
//!
//! fn main() {
//!     let mut hasher = Hasher::default();
//!     let hash = hasher
//!         .with_password("P@ssw0rd")
//!         .with_secret_key("\
//!             secret key that you should really store in a .env file \
//!             instead of in code, but this is just an example\
//!         ")
//!         .hash()
//!         .unwrap();
//!
//!     println!("{}", &hash);
//!     // 👆 prints a hash, which will be random since the default Hasher uses a random salt
//! }
//! ```
//! # Verifying
//!
//! Verifying passwords against a hash is equally as simple. Just instantiate a default
//! [`Verifier`](struct.Verifier.html), provide it with the password and the hash you would
//! like to compare, provide it with the secret key that was used to create the hash, and
//! then call the [`verify`](struct.Verifier.html#method.verify) method.
//! ```
//! extern crate argonautica;
//!
//! use argonautica::Verifier;
//!
//! fn main() {
//!     let mut verifier = Verifier::default();
//!     let is_valid = verifier
//!         .with_hash("
//!             $argon2id$v=19$m=4096,t=192,p=4$\
//!             o2y5PU86Vt+sr93N7YUGgC7AMpTKpTQCk4tNGUPZMY4$\
//!             yzP/ukZRPIbZg6PvgnUUobUMbApfF9RH6NagL9L4Xr4\
//!         ")
//!         .with_password("P@ssw0rd")
//!         .with_secret_key("\
//!             secret key that you should really store in a .env file \
//!             instead of in code, but this is just an example\
//!         ")
//!         .verify()
//!         .unwrap();
//!
//!     assert!(is_valid);
//! }
//! ```
//! # Alternatives
//!
//! If <b>argonautica</b> isn't your cup of tea, other Rust crates that will do Argon2 hashing for you
//! include [argon2rs](https://github.com/bryant/argon2rs) and
//! [rust-argon2](https://github.com/sru-systems/rust-argon2). If you're interesting
//! in password hashing with a different algorithm,
//! [rust-bcrypt](https://github.com/Keats/rust-bcrypt) might be worth checking out.
//!
//! For what it's worth, besides API differences, <b>argonautica</b> has three key features that
//! other crates currently lack:
//! * The ability to use [SIMD](https://en.wikipedia.org/wiki/SIMD) instructions (even on stable),
//!   which can lead to significantly faster hashing times
//!     * For example, on default settings, argonautica with SIMD runs <b>over twice
//!       as fast</b> as other crates on the developer's early-2014 Macbook, which has access to
//!       [SIMD instructions](https://software.intel.com/sites/landingpage/IntrinsicsGuide/)
//!       through
//!       [AVX2](https://en.wikipedia.org/wiki/Advanced_Vector_Extensions#Advanced_Vector_Extensions)
//!     * <i>Note: SIMD instructions are specific to your CPU; so if you're compiling for
//!       machines other than your own, you should not turn on the SIMD feature</i>
//! * The ability to hash passwords with a secret key, which not even the
//!   [C implementation](https://github.com/P-H-C/phc-winner-argon2) exposes publicly
//! * The newest Argon2 variant: Argon2id
//!
//! # Configuration
//!
//! The default configurations for [`Hasher`](struct.Hasher.html) and
//! [`Verifier`](struct.Verifier.html) were chosen to be reasonably secure for the general
//! use-case of hashing passwords for storage in a website database, but if you want to use
//! <b>argonautica</b> for different reasons or if you just disagree with the chosen defaults,
//! customizing <b>argonautica</b> to meet your needs should hopefully be as easy and as intuitive
//! as using the defaults.
//!
//! Here is an example that shows how to use [`Hasher`](struct.Hasher.html)'s custom
//! configuration options. It provides color on each of the options.
//! ```
//! extern crate argonautica;
//! extern crate futures_cpupool;
//!
//! use argonautica::Hasher;
//! use argonautica::config::{Backend, Variant, Version};
//! use futures_cpupool::CpuPool;
//!
//! fn main() {
//!     let mut hasher = Hasher::default();
//!     hasher
//!         .configure_backend(Backend::C) // Default is `Backend::C`
//!         // 👆 argonautica was designed to support multiple backends (meaning multiple
//!         // implementations of the underlying Argon2 algorithm). Currently only the C backend
//!         // is supported, which uses the cannonical Argon2 library written in C to actually
//!         // do the work. In the future hopefully a Rust backend will also be supported, but,
//!         // for the moment, you must use `Backend::C`, which is the default. Using
//!         // `Backend::Rust` will result in an error (again, for the moment).
//!         .configure_cpu_pool(CpuPool::new(2))
//!         // 👆 There are two non-blocking methods on `Hasher` that perform computation on
//!         // a separate thread and return a `Future` instead of a `Result` (`hash_non_blocking`
//!         // and `hash_raw_non_blocking`). These methods allow argonautica to play nicely with
//!         // futures-heavy code, but need a `CpuPool` in order to work. The blocking
//!         // methods `hash` and `hash_raw` do not use a 'CpuPool'; so if you are using only
//!         // these blocking methods you can ignore this configuration entirely. If, however,
//!         // you are using the non-blocking methods and would like to provide your own `CpuPool`
//!         // instead of using the default, which is a lazily created `CpuPool` with the number
//!         // of threads equal to the number of logical cores on your machine, you can
//!         // configure your `Hasher` with a custom `CpuPool` using this method. This
//!         // might be useful if, for example, you are writing code in an environment which
//!         // makes heavy use of futures, the code you are writing uses both a `Hasher` and
//!         // a `Verifier`, and you would like both of them to share the same underlying
//!         // `CpuPool`.
//!         .configure_hash_len(16) // Default is `32`
//!         // 👆 The hash length in bytes is configurable. The default is 32. This is probably
//!         // a good number to use. 16 is also probably fine. You probably shouldn't go below 16
//!         .configure_iterations(192) // Default is `192`
//!         // 👆 Argon2 has a notion of "iterations" or "time cost". All else equal and generally
//!         // speaking, the greater the number of iterations, the longer it takes to perform the
//!         // hash and the more secure the resulting hash. More iterations basically means more
//!         // CPU load. This and "memory size" (see below) are the two primary parameters to
//!         // adjust in order to increase or decrease the security of your hash. The default is
//!         // 192 iterations, which was chosen because, along with the default memory size of
//!         // 4096, this leads to a hashing time of approximately 300 milliseconds on the
//!         // early-2014 Macbook Air that is the developer's machine. If you're going to use
//!         // argonautica in production, you should probably tweak this parameter (and the memory
//!         // size parameter) in order to increase the time it takes to hash to the maximum you
//!         // can reasonably allow for your use-case (e.g. to probably about 300-500 milliseconds
//!         // for the use-case of hashing user passwords for a website)
//!         .configure_lanes(2) // Default is number of logical cores on your machine
//!         // 👆 Argon2 can break up its work into one or more "lanes" during some parts of
//!         // the hashing algorithm. If you configure it with multiple lanes and you also
//!         // use multiple threads (see below) the hashing algorithm will performed its
//!         // work in parallel in some parts, potentially speeding up the time it takes to
//!         // produce a hash without diminishing the security of the result. By default,
//!         // the number of lanes is set to the number of logical cores on your machine
//!         .configure_memory_size(4096) // Default is `4096`
//!         // 👆 Argon2 has a notion of "memory size" or "memory cost" (in kibibytes). All else
//!         // equal and generally speaking, the greater the memory size, the longer it takes to
//!         // perform the hash and the more secure the resulting hash. More memory size basically
//!         // means more memory used. This and "iterations" (see above) are, again, generally
//!         // speaking, the two parameters to adjust in order to increase or decrease the
//!         // security of your hash. The default is 4096 kibibytes, which was chosen because,
//!         // again, along with the default iterations of 192, this leads to a hashing time of
//!         // approximately 300 milliseconds on the early-2014 Macbook Air that is the
//!         // developer's machine. If you're going to use argonautica in production, you should
//!         // probably tweak this parameter (and the iterations parameter) in order to increase
//!         // the time it takes to hash to the maximum you can reasonably allow for your use-case
//!         // (e.g. to probably about 300-500 milliseconds for the use-case of hashing user
//!         // passwords for a website)
//!         .configure_password_clearing(false) // Default is `false`
//!         // 👆 It is possible to have the underlying bytes of the password you provided
//!         // to `Hasher` be erased after each call to `hash`, `hash_raw` or their non-blocking
//!         // equivalents. If you want this extra security feature, set this configuration
//!         // to `true` (the default is `false`). If you set this configuration to `true`,
//!         // you will be required to provide `Hasher` with a mutable password (e.g.
//!         // a `String`, a `Vec<u8>`, a `&mut str`, or a `&mut [u8]` instead of a
//!         // `&str` or a `&[u8]`)
//!         .configure_secret_key_clearing(false) // Default is `false`
//!         // 👆 It is also possible to have the underlying bytes of the secret key you provided
//!         // to `Hasher` be erased after each call to `hash`, `hash_raw` or their non-blocking
//!         // equivalents. If you want this extra security feature, set this configuration
//!         // to `true` (the default is `false`). If you set this configuration to `true`,
//!         // you will be required to provide `Hasher` with a mutable secret key (e.g.
//!         // a `String`, a `Vec<u8>`, a `&mut str`, or a `&mut [u8]` instead of a `&str`
//!         // or a `&[u8]`)
//!         .configure_threads(2) // Default is number of logical cores on your machine
//!         // 👆 If you have configured `Hasher` to use more than one lane (see above), you
//!         // can get the hashing algorithm to run in parallel during some parts of the
//!         // computation by setting the number of threads to be greater than one as well,
//!         // potentially speeding up the time it takes to produce a hash without diminishing
//!         // the security of the result. By default, the number of threads is set to the number
//!         // of logical cores on your machine. If you set the number of threads to a number
//!         // greater than the number of lanes, `Hasher` will automatically reduce the number
//!         // of threads to the number of lanes
//!         .configure_variant(Variant::Argon2id) // Default is `Variant::Argon2id`
//!         // 👆 Argon2 has three variants: Argon2d, Argon2i, and Argon2id. Here is how these
//!         // variants are explained in the RFC: "Argon2 has one primary variant: Argon2id,
//!         // and two supplementary variants: Argon2d and Argon2i. Argon2d uses data-dependent
//!         // memory access, which makes it suitable for ... applications with no threats from
//!         // side-channel timing attacks. Argon2i uses data-independent memory access, which
//!         // is preferred for password hashing and password-based key derivation. Argon2id
//!         // works as Argon2i for the first half of the first iteration over the memory, and
//!         // as Argon2d for the rest, thus providing both side-channel attack protection and
//!         // brute-force cost savings due to time-memory tradeoffs." If you do not know which
//!         // variant to use, use the default, which is Argon2id
//!         .configure_version(Version::_0x13) // Default is `Version::_0x13`
//!         // 👆 Argon2 has two versions: 0x10 and 0x13. The latest version is 0x13 (as of 5/18).
//!         // Unless you have a very specific reason not to, you should use the latest
//!         // version (0x13), which is also the default
//!         .opt_out_of_secret_key(true); // Default is `false`
//!         // 👆 As an extra security measure, if you want to hash without a secret key, which
//!         // is not recommended, you must explicitly declare that this is your intention
//!         // by calling this method and setting the `opt_out_of_secret_key` configuration to
//!         // `true` (by default, it is set to `false`); otherwise hashing will return an error
//!         // when you fail to provide a secret key
//!
//!     let hash = hasher
//!         .with_password("P@ssw0rd")
//!         .with_salt("somesalt")
//!         .hash()
//!         .unwrap();
//!         // 👆 Note: We are able to hash witout a secret key because we explicitly
//!         // set `opt_out_of_secret_key` to `true` above
//!
//!     assert_eq!(
//!         &hash,
//!         "$argon2id$v=19$m=4096,t=192,p=2$c29tZXNhbHQ$sw41ZsxebJmOJ6vSHe6BGQ",
//!     );
//! }
//! ```
//! # Installation
//!
//! <b>argonautica</b> should be relatively straightforward to include in your Rust project:
//! * Place `extern crate argonautica;` in your code (typically in either `lib.rs` or `main.rs`)
//! * In the `[dependencies]` section of your `Cargo.toml`, place ...
//!     * ... if you're building for your own machine ...
//!         * `argonautica = { version = "0.1.0", features = ["simd"] }`, or
//!         * `argonautica = { version = "0.1.0", features = ["serde", "simd"] }`
//!     * ... if you're building for a different machine ...
//!         * `argonautica = "0.1.0"`, or
//!         * `argonautica = { version = "0.1.0", features = ["serde"] }`
//!
//! That said, <b>argonautica</b> uses [cc](https://github.com/alexcrichton/cc-rs) and
//! [bindgen](https://github.com/rust-lang-nursery/rust-bindgen) to compile the cannonical
//! [C implemenation](https://github.com/P-H-C/phc-winner-argon2) of Argon2 into a
//! static archive during the build process. This means you need a C compiler on your
//! machine in order to build <b>argonautica</b>. More specifically, you need:
//! * [LLVM/Clang](https://llvm.org/) (version 3.9 or higher)
//!     * Mac OS: `brew install llvm`, which requires [Homebrew](https://brew.sh/)
//!     * Debian-based linux: `apt-get install clang llvm-dev libclang-dev`
//!     * Arch linux: `pacman -S clang`
//!     * Windows: Download a pre-built binary [here](http://releases.llvm.org/download.html)
//!
//! <b>argonautica</b> runs on stable Rust version 1.26.0 or greater.
//!
//! # License
//!
//! <b>argonautica</b> is licensed under either of:
//! * [The Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0), or
//! * [The MIT license](http://opensource.org/licenses/MIT)
//!
//! at your option.

#![deny(
    missing_debug_implementations, missing_docs, unused_imports, unused_unsafe, unused_variables
)]
#![doc(html_root_url = "https://docs.rs/argonautica/0.1.5")]

extern crate base64;
#[macro_use]
extern crate bitflags;
#[cfg(feature = "development")]
extern crate blake2_rfc;
#[macro_use]
extern crate failure;
extern crate futures;
extern crate futures_cpupool;
extern crate libc;
#[macro_use]
extern crate log;
#[macro_use]
extern crate nom;
extern crate num_cpus;
extern crate rand;
extern crate scopeguard;
#[cfg(feature = "serde")]
#[macro_use]
extern crate serde;
#[cfg(all(test, feature = "serde"))]
extern crate serde_json;

mod backend;
mod error;
mod error_kind;
mod ffi;
mod hasher;
mod verifier;

pub mod config;
pub use error::Error;
pub use error_kind::ErrorKind;
pub use hasher::Hasher;
pub mod input;
pub mod output;
pub mod utils;
pub use verifier::Verifier;