secure_password/
lib.rs

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
14// use std::convert::AsRef;
15use std::borrow::Borrow;
16use std::rc::Rc;
17use std::str;
18
19thread_local! {
20  // Uses libsodium's defaults
21  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
34/// Hash a password.
35pub 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
44/// Verify a password against a hash.
45pub 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}