resolved with bytes-encodable issue
This commit is contained in:
parent
9895f00e5e
commit
63f6ab4e6d
@ -256,6 +256,49 @@ impl<T> Populatable for [T] where T: Sized {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
/// Bytes array deserialization error
|
||||||
|
pub enum FromBytesError {
|
||||||
|
/// Not enough bytes for the requested type
|
||||||
|
NotLongEnough,
|
||||||
|
/// Too many bytes for the requested type
|
||||||
|
TooLong,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Value that can be serialized from bytes array
|
||||||
|
pub trait FromRawBytes : Sized {
|
||||||
|
/// function that will instantiate and initialize object from slice
|
||||||
|
fn from_bytes(d: &[u8]) -> Result<Self, FromBytesError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> FromRawBytes for T where T: Sized + FixedHash {
|
||||||
|
fn from_bytes(bytes: &[u8]) -> Result<Self, FromBytesError> {
|
||||||
|
use std::mem;
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
match bytes.len().cmp(&mem::size_of::<T>()) {
|
||||||
|
Ordering::Less => return Err(FromBytesError::NotLongEnough),
|
||||||
|
Ordering::Greater => return Err(FromBytesError::TooLong),
|
||||||
|
Ordering::Equal => ()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut res: Self = unsafe { mem::uninitialized() };
|
||||||
|
res.copy_raw(bytes);
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRawBytes for String {
|
||||||
|
fn from_bytes(bytes: &[u8]) -> Result<String, FromBytesError> {
|
||||||
|
Ok(::std::str::from_utf8(bytes).unwrap().to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRawBytes for Vec<u8> {
|
||||||
|
fn from_bytes(bytes: &[u8]) -> Result<Vec<u8>, FromBytesError> {
|
||||||
|
Ok(bytes.clone().to_vec())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn fax_raw() {
|
fn fax_raw() {
|
||||||
let mut x = [255u8; 4];
|
let mut x = [255u8; 4];
|
||||||
|
@ -232,7 +232,7 @@ impl KeyFileCrypto {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Ok(KeyFileCrypto {
|
Ok(KeyFileCrypto {
|
||||||
cipher_text: Bytes::from(cipher_text),
|
cipher_text: match FromHex::from_hex(cipher_text) { Ok(bytes) => bytes, Err(_) => { return Err(CryptoParseError::InvalidCipherText); } },
|
||||||
cipher_type: cipher_type,
|
cipher_type: cipher_type,
|
||||||
kdf: kdf,
|
kdf: kdf,
|
||||||
mac: mac,
|
mac: mac,
|
||||||
|
@ -32,14 +32,14 @@ const KEY_LENGTH_AES_USIZE: usize = KEY_LENGTH_AES as usize;
|
|||||||
/// Encrypted hash-map, each request should contain password
|
/// Encrypted hash-map, each request should contain password
|
||||||
pub trait EncryptedHashMap<Key: Hash + Eq> {
|
pub trait EncryptedHashMap<Key: Hash + Eq> {
|
||||||
/// Returns existing value for the key, if any
|
/// Returns existing value for the key, if any
|
||||||
fn get<Value: Populatable + Default + BytesConvertable>(&self, key: &Key, password: &str) -> Result<Value, EncryptedHashMapError>;
|
fn get<Value: FromRawBytes + BytesConvertable>(&self, key: &Key, password: &str) -> Result<Value, EncryptedHashMapError>;
|
||||||
/// Insert new encrypted key-value and returns previous if there was any
|
/// Insert new encrypted key-value and returns previous if there was any
|
||||||
fn insert<Value: Populatable + Default + BytesConvertable>(&mut self, key: Key, value: Value, password: &str) -> Option<Value>;
|
fn insert<Value: FromRawBytes + BytesConvertable>(&mut self, key: Key, value: Value, password: &str) -> Option<Value>;
|
||||||
/// Removes key-value by key and returns the removed one, if any exists and password was provided
|
/// Removes key-value by key and returns the removed one, if any exists and password was provided
|
||||||
fn remove<Value: Populatable + Default + BytesConvertable> (&mut self, key: &Key, password: Option<&str>) -> Option<Value>;
|
fn remove<Value: FromRawBytes + BytesConvertable> (&mut self, key: &Key, password: Option<&str>) -> Option<Value>;
|
||||||
/// Deletes key-value by key and returns if the key-value existed
|
/// Deletes key-value by key and returns if the key-value existed
|
||||||
fn delete(&mut self, key: &Key) -> bool {
|
fn delete(&mut self, key: &Key) -> bool {
|
||||||
self.remove::<&[u8]>(key, None).is_some()
|
self.remove::<Bytes>(key, None).is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +49,9 @@ pub enum EncryptedHashMapError {
|
|||||||
/// Encryption failed
|
/// Encryption failed
|
||||||
InvalidPassword,
|
InvalidPassword,
|
||||||
/// No key in the hashmap
|
/// No key in the hashmap
|
||||||
UnknownIdentifier
|
UnknownIdentifier,
|
||||||
|
/// Stored value is not well formed for the requested type
|
||||||
|
InvalidValueFormat(FromBytesError),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represent service for storing encrypted arbitrary data
|
/// Represent service for storing encrypted arbitrary data
|
||||||
@ -96,14 +98,16 @@ fn derive_mac(derived_left_bits: &[u8], cipher_text: &[u8]) -> Bytes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EncryptedHashMap<H128> for SecretStore {
|
impl EncryptedHashMap<H128> for SecretStore {
|
||||||
fn get<Value: Populatable + Default + BytesConvertable>(&self, key: &H128, password: &str) -> Result<Value, EncryptedHashMapError> {
|
fn get<Value: FromRawBytes + BytesConvertable>(&self, key: &H128, password: &str) -> Result<Value, EncryptedHashMapError> {
|
||||||
match self.directory.get(key) {
|
match self.directory.get(key) {
|
||||||
Some(key_file) => {
|
Some(key_file) => {
|
||||||
let decrypted_bytes = match key_file.crypto.kdf {
|
let decrypted_bytes = match key_file.crypto.kdf {
|
||||||
KeyFileKdf::Pbkdf2(ref params) => {
|
KeyFileKdf::Pbkdf2(ref params) => {
|
||||||
let (derived_left_bits, derived_right_bits) = derive_key(password, ¶ms.salt);
|
let (derived_left_bits, derived_right_bits) = derive_key_iterations(password, ¶ms.salt, params.c);
|
||||||
let expected_mac = derive_mac(&derived_right_bits, &key_file.crypto.cipher_text).sha3();
|
//assert_eq!(derive_mac(&derived_right_bits, &key_file.crypto.cipher_text).to_hex(), "");
|
||||||
if expected_mac != key_file.crypto.mac { return Err(EncryptedHashMapError::InvalidPassword); }
|
assert_eq!(&key_file.crypto.cipher_text.to_hex(), "5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46");
|
||||||
|
if derive_mac(&derived_right_bits, &key_file.crypto.cipher_text)
|
||||||
|
.sha3() != key_file.crypto.mac { return Err(EncryptedHashMapError::InvalidPassword); }
|
||||||
|
|
||||||
let mut val = vec![0u8; key_file.crypto.cipher_text.len()];
|
let mut val = vec![0u8; key_file.crypto.cipher_text.len()];
|
||||||
match key_file.crypto.cipher_type {
|
match key_file.crypto.cipher_type {
|
||||||
@ -116,15 +120,16 @@ impl EncryptedHashMap<H128> for SecretStore {
|
|||||||
_ => { unimplemented!(); }
|
_ => { unimplemented!(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut instance = Value::default();
|
match Value::from_bytes(&decrypted_bytes) {
|
||||||
instance.populate_raw(&decrypted_bytes);
|
Ok(value) => Ok(value),
|
||||||
Ok(instance)
|
Err(bytes_error) => Err(EncryptedHashMapError::InvalidValueFormat(bytes_error))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
None => Err(EncryptedHashMapError::UnknownIdentifier)
|
None => Err(EncryptedHashMapError::UnknownIdentifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert<Value: Populatable + Default + BytesConvertable>(&mut self, key: H128, value: Value, password: &str) -> Option<Value> {
|
fn insert<Value: FromRawBytes + BytesConvertable>(&mut self, key: H128, value: Value, password: &str) -> Option<Value> {
|
||||||
let previous = if let Ok(previous_value) = self.get(&key, password) { Some(previous_value) } else { None };
|
let previous = if let Ok(previous_value) = self.get(&key, password) { Some(previous_value) } else { None };
|
||||||
|
|
||||||
// crypto random initiators
|
// crypto random initiators
|
||||||
@ -156,7 +161,7 @@ impl EncryptedHashMap<H128> for SecretStore {
|
|||||||
previous
|
previous
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove<Value: Populatable + Default + BytesConvertable>(&mut self, key: &H128, password: Option<&str>) -> Option<Value> {
|
fn remove<Value: FromRawBytes + BytesConvertable>(&mut self, key: &H128, password: Option<&str>) -> Option<Value> {
|
||||||
let previous = if let Some(pass) = password {
|
let previous = if let Some(pass) = password {
|
||||||
if let Ok(previous_value) = self.get(&key, pass) { Some(previous_value) } else { None }
|
if let Ok(previous_value) = self.get(&key, pass) { Some(previous_value) } else { None }
|
||||||
}
|
}
|
||||||
@ -229,7 +234,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
let sstore = SecretStore::new_test(&temp);
|
let sstore = SecretStore::new_test(&temp);
|
||||||
if let Ok(_) = sstore.get::<Bytes>(&H128::from_str("3198bc9c66725ab3d9954942343ae5b6").unwrap(), "testpassword") {
|
if let Ok(_) = sstore.get::<Bytes>(&H128::from_str("3198bc9c66725ab3d9954942343ae5b6").unwrap(), "testpassword") {
|
||||||
panic!("shoud be error loading key, we requested the wrong key");
|
panic!("should be error loading key, we requested the wrong key");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user