1#![cfg_attr(feature = "nightly", deny(missing_docs))]
2#![cfg_attr(feature = "nightly", feature(external_doc))]
3#![cfg_attr(feature = "nightly", doc(include = "../README.md"))]
4#![cfg_attr(test, deny(warnings))]
5
6extern crate argon2;
7extern crate failure;
8extern crate rand;
9
10use argon2::{Config, ThreadMode, Variant, Version};
11use failure::Error;
12use rand::prelude::*;
13
14use std::borrow::Borrow;
16use std::rc::Rc;
17use std::str;
18
19thread_local! {
20 static CONFIG: Rc<Config<'static>> = Rc::new(Config {
22 variant: Variant::Argon2id,
23 version: Version::Version13,
24 mem_cost: 65536,
25 time_cost: 2,
26 lanes: 1,
27 thread_mode: ThreadMode::Sequential,
28 secret: &[],
29 ad: &[],
30 hash_length: 32,
31 });
32}
33
34pub fn hash(password: &[u8]) -> Result<Vec<u8>, Error> {
36 let salt = random_bytes();
37 let res = CONFIG.with(|config| {
38 let config = config.borrow();
39 argon2::hash_encoded(password, &salt, &config)
40 })?;
41 Ok(res.into_bytes())
42}
43
44pub fn verify(password: &[u8], hash: &[u8]) -> Result<bool, Error> {
46 let hash = str::from_utf8(hash)?;
47 let matches = argon2::verify_encoded(&hash, password)?;
48 Ok(matches)
49}
50
51fn random_bytes() -> Vec<u8> {
52 let mut rng = rand::thread_rng();
53 let mut res = vec![0; 256];
54 rng.fill_bytes(&mut res);
55 res
56}