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
//! Password Hashing.
//!
//! Sarkara use [`Argon2i`](https://github.com/P-H-C/phc-winner-argon2),
//! it based on [`Blake2`](https://blake2.net/) hashing function,
//! is [Password Hashing Competition](https://password-hashing.net/) winner.


mod argon2;

use std::fmt;
use std::error::Error;
use seckey::Bytes;
pub use self::argon2::{
    Argon2i,
    OPSLIMIT_INTERACTIVE, MEMLIMIT_INTERACTIVE,
    OPSLIMIT_MODERATE, MEMLIMIT_MODERATE,
    OPSLIMIT_SENSITIVE, MEMLIMIT_SENSITIVE
};


/// Key derivation error.
#[derive(Clone, Debug)]
pub enum KeyDerivationFail {
    /// parameter error.
    ParameterError(String),
    /// Output length too short.
    OutLenTooShort,
    /// Output length too long.
    OutLenTooLong,
    /// Salt too short.
    SaltTooShort,
    /// Salt too long.
    SaltTooLong
}

/// `KeyDerive` trait.
pub trait KeyDerive: Default {
    /// Set output length.
    fn with_size(&mut self, len: usize) -> &mut Self;
    /// Set key.
    fn with_key(&mut self, key: &[u8]) -> &mut Self;
    /// Set associated data.
    fn with_aad(&mut self, aad: &[u8]) -> &mut Self;
    /// Set opslimit parameter.
    fn with_opslimit(&mut self, opslimit: u32) -> &mut Self;
    /// Set memlimit parameter.
    fn with_memlimit(&mut self, memlimit: u32) -> &mut Self;

    /// Derive key.
    ///
    /// ## Fail When:
    /// * Param Error, see [`ParamErr`](../../argon2rs/enum.ParamErr.html)
    fn derive<K>(&self, password: &[u8], salt: &[u8])
        -> Result<K, KeyDerivationFail>
        where K: From<Vec<u8>>;
}

/// `KeyVerify` trait.
pub trait KeyVerify: KeyDerive {
    /// Verify password hash.
    ///
    /// ## Fail When:
    /// * Param Error, see [`ParamErr`](../../argon2rs/enum.ParamErr.html)
    fn verify(&self, password: &[u8], salt: &[u8], hash: &[u8]) -> Result<bool, KeyDerivationFail> {
        Ok(self.derive::<Bytes>(password, salt)? == hash)
    }
}

impl<T> KeyVerify for T where T: KeyDerive {}

impl fmt::Display for KeyDerivationFail {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

impl Error for KeyDerivationFail {
    fn description(&self) -> &str {
        match *self {
            KeyDerivationFail::ParameterError(ref string) => string,
            KeyDerivationFail::OutLenTooShort => "Output length too short.",
            KeyDerivationFail::OutLenTooLong => "Output length too long.",
            KeyDerivationFail::SaltTooShort => "Salt too short.",
            KeyDerivationFail::SaltTooLong => "Salt too long."
        }
    }
}