This commit is contained in:
Nikolay Volf 2016-02-11 03:32:44 +03:00
parent 7bfb832312
commit e19b89be2c

View File

@ -24,18 +24,8 @@ enum CryptoCipherType {
Aes128Ctr(U128) Aes128Ctr(U128)
} }
enum KeyFileKdf {
Pbkdf2(KdfPbkdf2Params),
Scrypt(KdfScryptParams)
}
struct KeyFileCrypto {
cipher: CryptoCipherType,
Kdf: KeyFileKdf,
}
enum KeyFileVersion { enum KeyFileVersion {
V1, V2, V3 V3(u64)
} }
enum Pbkdf2CryptoFunction { enum Pbkdf2CryptoFunction {
@ -56,6 +46,22 @@ struct KdfPbkdf2Params {
prf: Pbkdf2CryptoFunction prf: Pbkdf2CryptoFunction
} }
#[derive(Debug)]
enum KdfPbkdf2ParseError {
InvalidParameter(String)
}
impl KdfPbkdf2Params {
fn new(_json: &Json) -> Result<KdfPbkdf2Params, KdfPbkdf2ParseError> {
KdfPbkdf2Params{
dkLen: 0,
salt: H256::zero(),
c: 0,
prf: Pbkdf2CryptoFunction::HMacSha256
}
}
}
#[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
@ -70,15 +76,157 @@ struct KdfScryptParams {
r: u32, r: u32,
} }
type Uuid = String; #[derive(Debug)]
enum ScryptParseError {
InvalidParameter(String)
}
impl KdfScryptParams {
fn new(_json: &Json) -> Result<KdfScryptParams, KdfPbkdf2ParseError> {
Ok(KdfScryptParams{
dkLen: 0,
p: 0,
n: 0,
r: 0
})
}
}
enum Kdf { enum Kdf {
Pbkdf2(KdfPbkdf2Params), Pbkdf2(KdfPbkdf2Params),
Scrypt(KdfScryptParams) Scrypt(KdfScryptParams)
} }
enum KeyFileKdf {
Pbkdf2(KdfPbkdf2Params),
Scrypt(KdfScryptParams)
}
struct KeyFileCrypto {
cipher_type: CryptoCipherType,
cipher_text: Bytes,
kdf: KeyFileKdf,
}
impl KeyFileCrypto {
fn new(json: &Json) -> Result<KeyFileCrypto, CryptoParseError> {
let as_object = match json.as_object() {
None => { return Err(CryptoParseError::InvalidJsonFormat); }
Some(obj) => obj
};
let cipher_type = match as_object["cipher"].as_string() {
None => { return Err(CryptoParseError::NoCipherType); }
Some("aes-128-ctr") => CryptoCipherType::Aes128Ctr(
match as_object["cipherparams"].as_string() {
None => { return Err(CryptoParseError::NoCipherParameters); },
Some(cipher_param) => H128::from(cipher_param)
}
),
Some(oter_cipher_type) => {
return Err(CryptoParseError::InvalidCipherType(
Mismatch { expected: "aes-128-ctr".to_owned(), found: other_cipher_type.to_owned() }));
}
};
let kdf = match (as_object["kdf"].as_string(), as_object["kdfparams"]) {
(None, _) => { return Err(CryptoParseError::NoKdfType); },
(_, None) => { return Err(CryptoParseError::NoKdfParams); },
(Some("scrypt"), Some(kdf_params)) =>
match KdfScryptParams::new(kdf_params) {
Err(scrypt_params_error) => return Err(CryptoParseError::Scrypt(scrypt_params_error)),
Ok(scrypt_params) => scrypt_params
},
(Some("pbkdf2"), Some(kdf_params)) =>
match KdfPbkdf2Params::new(kdf_params) {
Err(kdfPbkdf2_params_error) => return Err(CryptoParseError::Scrypt(scrypt_params_error)),
Ok(kdfPbkdf2_params) => kdfPbkdf2_params
},
(Some(other_kdf), _) => {
return Err(CryptoParseError::InvalidKdfType(
Mismatch { expected: "pbkdf2/scrypt".to_owned(), found: other_kdf.to_ownded()}));
}
};
let cipher_text = match as_object["ciphertext"].as_string() {
None => { return Err(CryptoParseError::NoCipherText); }
Some(text) => text
};
Ok(KeyFileCrypto {
cipher_text: Bytes::from(cipher_text),
cipher_type: cipher_type,
kdf: kdf,
})
}
}
type Uuid = String;
struct KeyFileContent { struct KeyFileContent {
version: KeyFileVersion, version: KeyFileVersion,
crypto: KeyFileCrypto, crypto: KeyFileCrypto,
id: Uuid id: Uuid
} }
#[derive(Debug)]
enum CryptoParseError {
InvalidJsonFormat,
InvalidCryptoVersion,
NoCryptoVersion,
InvalidKdfType(Mismatch<String>),
InvalidCipherType(Mismatch<String>),
NoCipherText,
NoKdfType,
NoKdfParams,
Scrypt(ScryptParseError),
KdfPbkdf2(KdfPbkdf2ParseError)
}
#[derive(Debug)]
enum KeyFileParseError {
InvalidVersion,
UnsupportedVersion(OutOfBounds<u64>),
InvalidJsonFormat,
NoIdentifier,
NoCryptoSection,
Crypto(CryptoParseError),
}
impl KeyFileContent {
fn new(json: &Json) -> Result<KeyFileContent, KeyFileParseError> {
let as_object = match json.as_object() {
None => { return Err(KeyFileParseError::InvalidJsonFormat); },
Some(obj) => obj
};
let version = match as_object["version"].as_u64() {
None => { return Err(KeyFileParseError::InvalidVersion); },
Some(json_version) => {
if json_version <= 2 {
return Err(KeyFileParseError::UnsupportedVersion(OutOfBounds { min: Some(3), max: None, found: json_version }))
};
KeyFileVersion::V3(json_version)
}
};
let id = match as_object["id"].as_string() {
None => { return Err(KeyFileParseError::NoIdentifier); },
Some(id) => id
};
let crypto = match as_object.get("crypto") {
None => { return Err(KeyFileParseError::NoCryptoSection); }
Some(crypto_json) => match KeyFileCrypto::new(crypto_json) {
Ok(crypto) => crypto,
Err(crypto_error) => { return Err(KeyFileParseError::Crypto(crypto_error)); }
}
};
Ok(KeyFileContent {
version: version,
id: id.to_owned(),
crypto: crypto
})
}
}