parsing tests

This commit is contained in:
Nikolay Volf 2016-02-11 16:17:38 +03:00
parent f0431218d6
commit e61376565e

View File

@ -19,15 +19,18 @@
use common::*; use common::*;
#[derive(PartialEq, Debug)]
enum CryptoCipherType { 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)]
enum KeyFileVersion { enum KeyFileVersion {
V3(u64) V3(u64)
} }
#[derive(PartialEq, Debug)]
enum Pbkdf2CryptoFunction { enum Pbkdf2CryptoFunction {
HMacSha256 HMacSha256
} }
@ -48,16 +51,29 @@ struct KdfPbkdf2Params {
#[derive(Debug)] #[derive(Debug)]
enum Pbkdf2ParseError { enum Pbkdf2ParseError {
InvalidParameter(String) InvalidParameter(&'static str),
InvalidPrf(Mismatch<String>),
InvalidSaltFormat(UtilError),
MissingParameter(&'static str),
} }
impl KdfPbkdf2Params { impl KdfPbkdf2Params {
fn new(_json: &BTreeMap<String, Json>) -> Result<KdfPbkdf2Params, Pbkdf2ParseError> { fn new(json: &BTreeMap<String, Json>) -> Result<KdfPbkdf2Params, Pbkdf2ParseError> {
Ok(KdfPbkdf2Params{ Ok(KdfPbkdf2Params{
dkLen: 0, salt: match try!(json.get("salt").ok_or(Pbkdf2ParseError::MissingParameter("salt"))).as_string() {
salt: H256::zero(), None => { return Err(Pbkdf2ParseError::InvalidParameter("salt")) },
c: 0, Some(salt_value) => match H256::from_str(salt_value) {
prf: Pbkdf2CryptoFunction::HMacSha256 Ok(salt_hex_value) => salt_hex_value,
Err(from_hex_error) => { return Err(Pbkdf2ParseError::InvalidSaltFormat(from_hex_error)); },
}
},
prf: match try!(json.get("prf").ok_or(Pbkdf2ParseError::MissingParameter("prf"))).as_string() {
Some("hmac-sha256") => Pbkdf2CryptoFunction::HMacSha256,
Some(unexpected_prf) => { return Err(Pbkdf2ParseError::InvalidPrf(Mismatch { expected: "hmac-sha256".to_owned(), found: unexpected_prf.to_owned() })); },
None => { return Err(Pbkdf2ParseError::InvalidParameter("prf")); },
},
dkLen: try!(try!(json.get("dklen").ok_or(Pbkdf2ParseError::MissingParameter("dklen"))).as_u64().ok_or(Pbkdf2ParseError::InvalidParameter("dkLen"))) as u32,
c: try!(try!(json.get("c").ok_or(Pbkdf2ParseError::MissingParameter("c"))).as_u64().ok_or(Pbkdf2ParseError::InvalidParameter("c"))) as u32,
}) })
} }
} }
@ -74,29 +90,36 @@ struct KdfScryptParams {
n: u32, n: u32,
// TODO: comment // TODO: comment
r: u32, r: u32,
// cryptographic salt
salt: H256,
} }
#[derive(Debug)] #[derive(Debug)]
enum ScryptParseError { enum ScryptParseError {
InvalidParameter(String) InvalidParameter(&'static str),
InvalidPrf(Mismatch<String>),
InvalidSaltFormat(UtilError),
MissingParameter(&'static str),
} }
impl KdfScryptParams { impl KdfScryptParams {
fn new(_json: &BTreeMap<String, Json>) -> Result<KdfScryptParams, ScryptParseError> { fn new(json: &BTreeMap<String, Json>) -> Result<KdfScryptParams, ScryptParseError> {
Ok(KdfScryptParams{ Ok(KdfScryptParams{
dkLen: 0, salt: match try!(json.get("salt").ok_or(ScryptParseError::MissingParameter("salt"))).as_string() {
p: 0, None => { return Err(ScryptParseError::InvalidParameter("salt")) },
n: 0, Some(salt_value) => match H256::from_str(salt_value) {
r: 0 Ok(salt_hex_value) => salt_hex_value,
Err(from_hex_error) => { return Err(ScryptParseError::InvalidSaltFormat(from_hex_error)); },
}
},
dkLen: try!(try!(json.get("dklen").ok_or(ScryptParseError::MissingParameter("dklen"))).as_u64().ok_or(ScryptParseError::InvalidParameter("dkLen"))) as u32,
p: try!(try!(json.get("p").ok_or(ScryptParseError::MissingParameter("p"))).as_u64().ok_or(ScryptParseError::InvalidParameter("p"))) as u32,
n: try!(try!(json.get("n").ok_or(ScryptParseError::MissingParameter("n"))).as_u64().ok_or(ScryptParseError::InvalidParameter("n"))) as u32,
r: try!(try!(json.get("r").ok_or(ScryptParseError::MissingParameter("r"))).as_u64().ok_or(ScryptParseError::InvalidParameter("r"))) as u32,
}) })
} }
} }
enum Kdf {
Pbkdf2(KdfPbkdf2Params),
Scrypt(KdfScryptParams)
}
enum KeyFileKdf { enum KeyFileKdf {
Pbkdf2(KdfPbkdf2Params), Pbkdf2(KdfPbkdf2Params),
Scrypt(KdfScryptParams) Scrypt(KdfScryptParams)
@ -198,7 +221,7 @@ enum KeyFileParseError {
InvalidVersion, InvalidVersion,
UnsupportedVersion(OutOfBounds<u64>), UnsupportedVersion(OutOfBounds<u64>),
InvalidJsonFormat, InvalidJsonFormat,
NoIdentifier, InvalidIdentifier,
NoCryptoSection, NoCryptoSection,
Crypto(CryptoParseError), Crypto(CryptoParseError),
} }
@ -220,10 +243,7 @@ impl KeyFileContent {
} }
}; };
let id = match as_object["id"].as_string() { let id = try!(as_object.get("id").and_then(|json| json.as_string()).ok_or(KeyFileParseError::InvalidIdentifier));
None => { return Err(KeyFileParseError::NoIdentifier); },
Some(id) => id
};
let crypto = match as_object.get("crypto") { let crypto = match as_object.get("crypto") {
None => { return Err(KeyFileParseError::NoCryptoSection); } None => { return Err(KeyFileParseError::NoCryptoSection); }
@ -240,3 +260,166 @@ impl KeyFileContent {
}) })
} }
} }
#[cfg(test)]
mod tests {
use super::{KeyFileContent, KeyFileVersion, KeyFileKdf, KeyFileParseError};
use common::*;
#[test]
fn can_read_keyfile() {
let json = Json::from_str(
r#"
{
"crypto" : {
"cipher" : "aes-128-ctr",
"cipherparams" : {
"iv" : "6087dab2f9fdbbfaddc31a909735c1e6"
},
"ciphertext" : "5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46",
"kdf" : "pbkdf2",
"kdfparams" : {
"c" : 262144,
"dklen" : 32,
"prf" : "hmac-sha256",
"salt" : "ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd"
},
"mac" : "517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2"
},
"id" : "3198bc9c-6672-5ab3-d995-4942343ae5b6",
"version" : 3
}
"#).unwrap();
match KeyFileContent::new(&json) {
Ok(key_file) => {
assert_eq!(KeyFileVersion::V3(3), key_file.version)
},
Err(e) => panic!("Error parsing valid file: {:?}", e)
}
}
#[test]
fn can_read_scrypt_krf() {
let json = Json::from_str(
r#"
{
"crypto" : {
"cipher" : "aes-128-ctr",
"cipherparams" : {
"iv" : "83dbcc02d8ccb40e466191a123791e0e"
},
"ciphertext" : "d172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c",
"kdf" : "scrypt",
"kdfparams" : {
"dklen" : 32,
"n" : 262144,
"r" : 1,
"p" : 8,
"salt" : "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19"
},
"mac" : "2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097"
},
"id" : "3198bc9c-6672-5ab3-d995-4942343ae5b6",
"version" : 3
}
"#).unwrap();
match KeyFileContent::new(&json) {
Ok(key_file) => {
match key_file.crypto.kdf {
KeyFileKdf::Scrypt(scrypt_params) => {},
_ => { panic!("expected kdf params of crypto to be of scrypt type" ); }
}
},
Err(e) => panic!("Error parsing valid file: {:?}", e)
}
}
#[test]
fn can_return_error_no_id() {
let json = Json::from_str(
r#"
{
"crypto" : {
"cipher" : "aes-128-ctr",
"cipherparams" : {
"iv" : "83dbcc02d8ccb40e466191a123791e0e"
},
"ciphertext" : "d172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c",
"kdf" : "scrypt",
"kdfparams" : {
"dklen" : 32,
"n" : 262144,
"r" : 1,
"p" : 8,
"salt" : "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19"
},
"mac" : "2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097"
},
"version" : 3
}
"#).unwrap();
match KeyFileContent::new(&json) {
Ok(key_file) => {
panic!("Should be error of no crypto section, got ok");
},
Err(KeyFileParseError::InvalidIdentifier) => { },
Err(other_error) => { panic!("should be error of no crypto section, got {:?}", other_error); }
}
}
#[test]
fn can_return_error_no_crypto() {
let json = Json::from_str(
r#"
{
"id" : "3198bc9c-6672-5ab3-d995-4942343ae5b6",
"version" : 3
}
"#).unwrap();
match KeyFileContent::new(&json) {
Ok(key_file) => {
panic!("Should be error of no identifier, got ok");
},
Err(KeyFileParseError::NoCryptoSection) => { },
Err(other_error) => { panic!("should be error of no identifier, got {:?}", other_error); }
}
}
#[test]
fn can_return_error_unsupported_version() {
let json = Json::from_str(
r#"
{
"crypto" : {
"cipher" : "aes-128-ctr",
"cipherparams" : {
"iv" : "83dbcc02d8ccb40e466191a123791e0e"
},
"ciphertext" : "d172bf743a674da9cdad04534d56926ef8358534d458fffccd4e6ad2fbde479c",
"kdf" : "scrypt",
"kdfparams" : {
"dklen" : 32,
"n" : 262144,
"r" : 1,
"p" : 8,
"salt" : "ab0c7876052600dd703518d6fc3fe8984592145b591fc8fb5c6d43190334ba19"
},
"mac" : "2103ac29920d71da29f15d75b4a16dbe95cfd7ff8faea1056c33131d846e3097"
},
"version" : 1
}
"#).unwrap();
match KeyFileContent::new(&json) {
Ok(key_file) => {
panic!("should be error of unsupported version, got ok");
},
Err(KeyFileParseError::UnsupportedVersion(_)) => { },
Err(other_error) => { panic!("should be error of unsupported version, got {:?}", other_error); }
}
}
}