From 9f4dfc187f14e11db86ca1868821d0653558cfc2 Mon Sep 17 00:00:00 2001 From: Avril Date: Tue, 29 Sep 2020 15:16:23 +0100 Subject: [PATCH] password hash --- Cargo.toml | 2 +- src/password.rs | 59 ++++++++++++++++++++++++++++++++++++++++++++++++- src/sha256.rs | 9 ++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bba728a..8b231c7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cryptohelpers" -version = "1.2.0" +version = "1.3.0" license= "MIT" description = "Collection of helpers and simplifying functions for cryptography things" authors = ["Avril "] diff --git a/src/password.rs b/src/password.rs index cf3fb9a..7222805 100644 --- a/src/password.rs +++ b/src/password.rs @@ -18,7 +18,7 @@ pub const KEYSIZE: usize = consts::PASSWORD_KEYSIZE; pub const ROUNDS: u32 = consts::PASSWORD_ROUNDS; /// Represents a password hash -#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)] #[repr(transparent)] pub struct Password { derived: [u8; KEYSIZE], @@ -82,6 +82,7 @@ impl Salt { Self([0u8; SALTSIZE]) } + } impl From<[u8; SALTSIZE]> for Salt @@ -119,6 +120,31 @@ impl AsMut<[u8]> for Salt impl Password { + /// Create from a specific hash + #[inline] pub const fn from_bytes(derived: [u8; KEYSIZE]) -> Self + { + Self { derived } + } + + /// Consume into the hash bytes + #[inline] + pub const fn into_bytes(self) -> [u8; KEYSIZE] + { + self.derived + } + + /// Create an empty password hash container + #[inline(always)] pub const fn empty() -> Self + { + Self{derived: [0u8; KEYSIZE]} + } + + /// Create an AES key from this password hash + #[cfg(feature="aes")] + #[inline] pub fn create_aes(&self) -> aes::AesKey + { + aes::AesKey::from_slice(&self.derived[..consts::AES_KEYSIZE], &self.derived[consts::AES_KEYSIZE..]).unwrap() + } /// Validate this password. pub fn validate(&self, string: impl AsRef, salt: &Salt) -> bool { @@ -164,4 +190,35 @@ impl fmt::Display for Password } } +#[cfg(feature="aes")] +impl From for aes::AesKey +{ + #[inline] fn from(from: Password) -> Self + { + unsafe { + std::mem::transmute(from) + } + } +} + +#[cfg(test)] +mod tests +{ + use super::*; + #[test] + #[cfg(feature="aes")] + fn transmute_safe() + { + assert_eq!(std::mem::size_of::(), std::mem::size_of::()); + assert_eq!(std::mem::align_of::(), std::mem::align_of::()); + + let passwd = Password::derive("hello world", &Default::default()); + let naes = passwd.create_aes(); + let aes: aes::AesKey = passwd.into(); + + assert_eq!(aes, naes); + } +} + + pub use crate::error::password::Error; diff --git a/src/sha256.rs b/src/sha256.rs index 3ed612c..4e836ff 100644 --- a/src/sha256.rs +++ b/src/sha256.rs @@ -183,3 +183,12 @@ impl From for [u8; SIZE] from.hash } } + +#[cfg(feature="password")] +impl From for password::Password +{ + #[inline] fn from(from: Sha256Hash) -> Self + { + Self::from_bytes(from.hash) + } +}