Merge pull request #3490 from ethcore/scrypt-sweep-panics
Check for possible panics in scrypt key derivation
This commit is contained in:
commit
8befeb29a0
@ -34,16 +34,43 @@ pub const KEY_LENGTH: usize = 32;
|
|||||||
pub const KEY_ITERATIONS: usize = 10240;
|
pub const KEY_ITERATIONS: usize = 10240;
|
||||||
pub const KEY_LENGTH_AES: usize = KEY_LENGTH / 2;
|
pub const KEY_LENGTH_AES: usize = KEY_LENGTH / 2;
|
||||||
|
|
||||||
|
#[derive(PartialEq, Debug)]
|
||||||
|
pub enum ScryptError {
|
||||||
|
// log(N) < r / 16
|
||||||
|
InvalidN,
|
||||||
|
// p <= (2^31-1 * 32)/(128 * r)
|
||||||
|
InvalidP,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ScryptError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
let s = match *self {
|
||||||
|
ScryptError::InvalidN => "Invalid N argument of the scrypt encryption" ,
|
||||||
|
ScryptError::InvalidP => "Invalid p argument of the scrypt encryption",
|
||||||
|
};
|
||||||
|
|
||||||
|
write!(f, "{}", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
Secp(SecpError),
|
Secp(SecpError),
|
||||||
|
Scrypt(ScryptError),
|
||||||
InvalidMessage,
|
InvalidMessage,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ScryptError> for Error {
|
||||||
|
fn from(err: ScryptError) -> Self {
|
||||||
|
Error::Scrypt(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
let s = match *self {
|
let s = match *self {
|
||||||
Error::Secp(ref err) => err.to_string(),
|
Error::Secp(ref err) => err.to_string(),
|
||||||
|
Error::Scrypt(ref err) => err.to_string(),
|
||||||
Error::InvalidMessage => "Invalid message".into(),
|
Error::InvalidMessage => "Invalid message".into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -80,13 +107,23 @@ pub fn derive_key_iterations(password: &str, salt: &[u8; 32], c: u32) -> (Vec<u8
|
|||||||
(derived_right_bits.to_vec(), derived_left_bits.to_vec())
|
(derived_right_bits.to_vec(), derived_left_bits.to_vec())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn derive_key_scrypt(password: &str, salt: &[u8; 32], n: u32, p: u32, r: u32) -> (Vec<u8>, Vec<u8>) {
|
pub fn derive_key_scrypt(password: &str, salt: &[u8; 32], n: u32, p: u32, r: u32) -> Result<(Vec<u8>, Vec<u8>), Error> {
|
||||||
|
// sanity checks
|
||||||
|
let log_n = (32 - n.leading_zeros() - 1) as u8;
|
||||||
|
if log_n as u32 >= r * 16 {
|
||||||
|
return Err(Error::Scrypt(ScryptError::InvalidN));
|
||||||
|
}
|
||||||
|
|
||||||
|
if p as u64 > ((u32::max_value() as u64 - 1) * 32)/(128 * (r as u64)) {
|
||||||
|
return Err(Error::Scrypt(ScryptError::InvalidP));
|
||||||
|
}
|
||||||
|
|
||||||
let mut derived_key = vec![0u8; KEY_LENGTH];
|
let mut derived_key = vec![0u8; KEY_LENGTH];
|
||||||
let scrypt_params = ScryptParams::new(n.trailing_zeros() as u8, r, p);
|
let scrypt_params = ScryptParams::new(log_n, r, p);
|
||||||
scrypt(password.as_bytes(), salt, &scrypt_params, &mut derived_key);
|
scrypt(password.as_bytes(), salt, &scrypt_params, &mut derived_key);
|
||||||
let derived_right_bits = &derived_key[0..KEY_LENGTH_AES];
|
let derived_right_bits = &derived_key[0..KEY_LENGTH_AES];
|
||||||
let derived_left_bits = &derived_key[KEY_LENGTH_AES..KEY_LENGTH];
|
let derived_left_bits = &derived_key[KEY_LENGTH_AES..KEY_LENGTH];
|
||||||
(derived_right_bits.to_vec(), derived_left_bits.to_vec())
|
Ok((derived_right_bits.to_vec(), derived_left_bits.to_vec()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn derive_mac(derived_left_bits: &[u8], cipher_text: &[u8]) -> Vec<u8> {
|
pub fn derive_mac(derived_left_bits: &[u8], cipher_text: &[u8]) -> Vec<u8> {
|
||||||
|
@ -113,7 +113,7 @@ impl Crypto {
|
|||||||
|
|
||||||
let (derived_left_bits, derived_right_bits) = match self.kdf {
|
let (derived_left_bits, derived_right_bits) = match self.kdf {
|
||||||
Kdf::Pbkdf2(ref params) => crypto::derive_key_iterations(password, ¶ms.salt, params.c),
|
Kdf::Pbkdf2(ref params) => crypto::derive_key_iterations(password, ¶ms.salt, params.c),
|
||||||
Kdf::Scrypt(ref params) => crypto::derive_key_scrypt(password, ¶ms.salt, params.n, params.p, params.r),
|
Kdf::Scrypt(ref params) => try!(crypto::derive_key_scrypt(password, ¶ms.salt, params.n, params.p, params.r)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mac = crypto::derive_mac(&derived_right_bits, &self.ciphertext).keccak256();
|
let mac = crypto::derive_mac(&derived_right_bits, &self.ciphertext).keccak256();
|
||||||
|
Loading…
Reference in New Issue
Block a user