issues with loading and more tests
This commit is contained in:
parent
89c5d9f6f6
commit
19e1f63909
@ -23,24 +23,25 @@ const CURRENT_DECLARED_VERSION: u64 = 3;
|
|||||||
const MAX_KEY_FILE_LEN: u64 = 1024 * 80;
|
const MAX_KEY_FILE_LEN: u64 = 1024 * 80;
|
||||||
|
|
||||||
/// Cipher type (currently only aes-128-ctr)
|
/// Cipher type (currently only aes-128-ctr)
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
pub enum CryptoCipherType {
|
pub enum CryptoCipherType {
|
||||||
/// aes-128-ctr with 128-bit initialisation vector(iv)
|
/// aes-128-ctr with 128-bit initialisation vector(iv)
|
||||||
Aes128Ctr(U128)
|
Aes128Ctr(U128)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
enum KeyFileVersion {
|
enum KeyFileVersion {
|
||||||
V3(u64)
|
V3(u64)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// key generator function
|
/// key generator function
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
pub enum Pbkdf2CryptoFunction {
|
pub enum Pbkdf2CryptoFunction {
|
||||||
/// keyed-hash generator (HMAC-256)
|
/// keyed-hash generator (HMAC-256)
|
||||||
HMacSha256
|
HMacSha256
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
/// Kdf of type `Pbkdf2`
|
/// Kdf of type `Pbkdf2`
|
||||||
/// https://en.wikipedia.org/wiki/PBKDF2
|
/// https://en.wikipedia.org/wiki/PBKDF2
|
||||||
@ -94,6 +95,7 @@ impl KdfPbkdf2Params {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
/// Kdf of type `Scrypt`
|
/// Kdf of type `Scrypt`
|
||||||
/// https://en.wikipedia.org/wiki/Scrypt
|
/// https://en.wikipedia.org/wiki/Scrypt
|
||||||
@ -148,6 +150,7 @@ impl KdfScryptParams {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
/// Settings for password derived key geberator function
|
/// Settings for password derived key geberator function
|
||||||
pub enum KeyFileKdf {
|
pub enum KeyFileKdf {
|
||||||
/// Password-Based Key Derivation Function 2 (PBKDF2) type
|
/// Password-Based Key Derivation Function 2 (PBKDF2) type
|
||||||
@ -158,6 +161,7 @@ pub enum KeyFileKdf {
|
|||||||
Scrypt(KdfScryptParams)
|
Scrypt(KdfScryptParams)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
/// Encrypted password or other arbitrary message
|
/// Encrypted password or other arbitrary message
|
||||||
/// with settings for password derived key generator for decrypting content
|
/// with settings for password derived key generator for decrypting content
|
||||||
pub struct KeyFileCrypto {
|
pub struct KeyFileCrypto {
|
||||||
@ -309,6 +313,8 @@ fn uuid_from_string(s: &str) -> Result<Uuid, UtilError> {
|
|||||||
Ok(uuid)
|
Ok(uuid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
/// Stored key file struct with encrypted message (cipher_text)
|
/// Stored key file struct with encrypted message (cipher_text)
|
||||||
/// also contains password derivation function settings (PBKDF2/Scrypt)
|
/// also contains password derivation function settings (PBKDF2/Scrypt)
|
||||||
pub struct KeyFileContent {
|
pub struct KeyFileContent {
|
||||||
@ -340,6 +346,7 @@ enum KeyFileParseError {
|
|||||||
InvalidVersion,
|
InvalidVersion,
|
||||||
UnsupportedVersion(OutOfBounds<u64>),
|
UnsupportedVersion(OutOfBounds<u64>),
|
||||||
InvalidJsonFormat,
|
InvalidJsonFormat,
|
||||||
|
InvalidJson,
|
||||||
InvalidIdentifier,
|
InvalidIdentifier,
|
||||||
NoCryptoSection,
|
NoCryptoSection,
|
||||||
Crypto(CryptoParseError),
|
Crypto(CryptoParseError),
|
||||||
@ -413,7 +420,6 @@ impl KeyFileContent {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum KeyLoadError {
|
enum KeyLoadError {
|
||||||
InvalidEncoding,
|
|
||||||
FileTooLarge(OutOfBounds<u64>),
|
FileTooLarge(OutOfBounds<u64>),
|
||||||
FileParseError(KeyFileParseError),
|
FileParseError(KeyFileParseError),
|
||||||
FileReadError(::std::io::Error),
|
FileReadError(::std::io::Error),
|
||||||
@ -483,8 +489,8 @@ impl KeyDirectory {
|
|||||||
Ok(mut open_file) => {
|
Ok(mut open_file) => {
|
||||||
match open_file.metadata() {
|
match open_file.metadata() {
|
||||||
Ok(metadata) =>
|
Ok(metadata) =>
|
||||||
if metadata.len() > MAX_KEY_FILE_LEN { Err(KeyLoadError::FileTooLarge(OutOfBounds { min: Some(2), max: Some(MAX_KEY_FILE_LEN), found: metadata.len() })) }
|
if metadata.len() > MAX_KEY_FILE_LEN { Err(KeyLoadError::FileTooLarge(OutOfBounds { min: Some(2), max: Some(MAX_KEY_FILE_LEN), found: metadata.len() })) }
|
||||||
else { KeyDirectory::load_from_file(&mut open_file, metadata.len()) },
|
else { KeyDirectory::load_from_file(&mut open_file) },
|
||||||
Err(read_error) => Err(KeyLoadError::FileReadError(read_error))
|
Err(read_error) => Err(KeyLoadError::FileReadError(read_error))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -492,30 +498,25 @@ impl KeyDirectory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_from_file(file: &mut fs::File, size: u64) -> Result<KeyFileContent, KeyLoadError> {
|
fn load_from_file(file: &mut fs::File) -> Result<KeyFileContent, KeyLoadError> {
|
||||||
let mut json_data = vec![0u8; size as usize];
|
let mut buf = String::new();
|
||||||
|
match file.read_to_string(&mut buf) {
|
||||||
match file.read_to_end(&mut json_data) {
|
|
||||||
Ok(_) => {},
|
Ok(_) => {},
|
||||||
Err(read_error) => { return Err(KeyLoadError::FileReadError(read_error)); }
|
Err(read_error) => { return Err(KeyLoadError::FileReadError(read_error)); }
|
||||||
}
|
}
|
||||||
|
match Json::from_str(&buf) {
|
||||||
match ::std::str::from_utf8(&json_data) {
|
Ok(json) => match KeyFileContent::from_json(&json) {
|
||||||
Ok(ut8_string) => match Json::from_str(ut8_string) {
|
Ok(key_file_content) => Ok(key_file_content),
|
||||||
Ok(json) => match KeyFileContent::from_json(&json) {
|
Err(parse_error) => Err(KeyLoadError::FileParseError(parse_error))
|
||||||
Ok(key_file_content) => Ok(key_file_content),
|
|
||||||
Err(parse_error) => Err(KeyLoadError::FileParseError(parse_error))
|
|
||||||
},
|
|
||||||
Err(_) => Err(KeyLoadError::FileParseError(KeyFileParseError::InvalidJsonFormat))
|
|
||||||
},
|
},
|
||||||
Err(_) => Err(KeyLoadError::InvalidEncoding)
|
Err(_) => Err(KeyLoadError::FileParseError(KeyFileParseError::InvalidJson))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod file_tests {
|
||||||
use super::{KeyFileContent, KeyFileVersion, KeyFileKdf, KeyFileParseError, CryptoParseError, uuid_from_string, uuid_to_string, KeyFileCrypto};
|
use super::{KeyFileContent, KeyFileVersion, KeyFileKdf, KeyFileParseError, CryptoParseError, uuid_from_string, uuid_to_string, KeyFileCrypto};
|
||||||
use common::*;
|
use common::*;
|
||||||
|
|
||||||
@ -742,6 +743,38 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(loaded_key.id, key.id);
|
assert_eq!(loaded_key.id, key.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod directory_tests {
|
||||||
|
use super::{KeyDirectory, new_uuid, uuid_to_string, KeyFileContent, KeyFileCrypto};
|
||||||
|
use common::*;
|
||||||
|
use tests::helpers::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn key_directory_locates_keys() {
|
||||||
|
let temp_path = RandomTempPath::create_dir();
|
||||||
|
let directory = KeyDirectory::new(temp_path.as_path());
|
||||||
|
let uuid = new_uuid();
|
||||||
|
|
||||||
|
let path = directory.key_path(&uuid);
|
||||||
|
|
||||||
|
assert!(path.to_str().unwrap().contains(&uuid_to_string(&uuid)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn loads_key() {
|
||||||
|
let cipher_text: Bytes = FromHex::from_hex("a0f05555").unwrap();
|
||||||
|
let temp_path = RandomTempPath::create_dir();
|
||||||
|
let mut directory = KeyDirectory::new(&temp_path.as_path());
|
||||||
|
let uuid = directory.save(KeyFileContent::new(KeyFileCrypto::new_pbkdf2(cipher_text, U128::zero(), H256::random(), 32, 32))).unwrap();
|
||||||
|
let path = directory.key_path(&uuid);
|
||||||
|
|
||||||
|
let key = KeyDirectory::load_key(&path).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(key.id, uuid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -767,4 +800,31 @@ mod specs {
|
|||||||
|
|
||||||
assert!(uuid.is_ok());
|
assert!(uuid.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_load_key() {
|
||||||
|
let cipher_text: Bytes = FromHex::from_hex("a0f05555").unwrap();
|
||||||
|
let temp_path = RandomTempPath::create_dir();
|
||||||
|
let mut directory = KeyDirectory::new(&temp_path.as_path());
|
||||||
|
let uuid = directory.save(KeyFileContent::new(KeyFileCrypto::new_pbkdf2(cipher_text.clone(), U128::zero(), H256::random(), 32, 32))).unwrap();
|
||||||
|
|
||||||
|
let key = directory.get(&uuid).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(key.crypto.cipher_text, cipher_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn csn_store_10_keys() {
|
||||||
|
let temp_path = RandomTempPath::create_dir();
|
||||||
|
let mut directory = KeyDirectory::new(&temp_path.as_path());
|
||||||
|
|
||||||
|
let cipher_text: Bytes = FromHex::from_hex("a0f05555").unwrap();
|
||||||
|
let mut keys = Vec::new();
|
||||||
|
for _ in 0..10 {
|
||||||
|
let key = KeyFileContent::new(KeyFileCrypto::new_pbkdf2(cipher_text.clone(), U128::zero(), H256::random(), 32, 32));
|
||||||
|
keys.push(directory.save(key).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(10, keys.len())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user