sarkara 0.8.0

A Post-Quantum cryptography library.
//! 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.


pub mod argon2;

use std::fmt;
use std::error::Error;
use seckey::Bytes;
pub use self::argon2::Argon2i;


/// 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, "Key Derivation fail: {}", 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."
        }
    }
}