parsing tests
This commit is contained in:
parent
f0431218d6
commit
e61376565e
@ -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); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user