70 lines
2.6 KiB
Rust
70 lines
2.6 KiB
Rust
|
use tiny_keccak::Keccak;
|
||
|
use rcrypto::pbkdf2::pbkdf2;
|
||
|
use rcrypto::scrypt::{scrypt, ScryptParams};
|
||
|
use rcrypto::sha2::Sha256;
|
||
|
use rcrypto::hmac::Hmac;
|
||
|
|
||
|
pub const KEY_LENGTH: usize = 32;
|
||
|
pub const KEY_ITERATIONS: usize = 10240;
|
||
|
pub const KEY_LENGTH_AES: usize = KEY_LENGTH / 2;
|
||
|
|
||
|
pub fn derive_key_iterations(password: &str, salt: &[u8; 32], c: u32) -> (Vec<u8>, Vec<u8>) {
|
||
|
let mut h_mac = Hmac::new(Sha256::new(), password.as_bytes());
|
||
|
let mut derived_key = vec![0u8; KEY_LENGTH];
|
||
|
pbkdf2(&mut h_mac, salt, c, &mut derived_key);
|
||
|
let derived_right_bits = &derived_key[0..KEY_LENGTH_AES];
|
||
|
let derived_left_bits = &derived_key[KEY_LENGTH_AES..KEY_LENGTH];
|
||
|
(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>) {
|
||
|
let mut derived_key = vec![0u8; KEY_LENGTH];
|
||
|
let scrypt_params = ScryptParams::new(n.trailing_zeros() as u8, r, p);
|
||
|
scrypt(password.as_bytes(), salt, &scrypt_params, &mut derived_key);
|
||
|
let derived_right_bits = &derived_key[0..KEY_LENGTH_AES];
|
||
|
let derived_left_bits = &derived_key[KEY_LENGTH_AES..KEY_LENGTH];
|
||
|
(derived_right_bits.to_vec(), derived_left_bits.to_vec())
|
||
|
}
|
||
|
|
||
|
pub fn derive_mac(derived_left_bits: &[u8], cipher_text: &[u8]) -> Vec<u8> {
|
||
|
let mut mac = vec![0u8; KEY_LENGTH_AES + cipher_text.len()];
|
||
|
mac[0..KEY_LENGTH_AES].copy_from_slice(derived_left_bits);
|
||
|
mac[KEY_LENGTH_AES..cipher_text.len() + KEY_LENGTH_AES].copy_from_slice(cipher_text);
|
||
|
mac
|
||
|
}
|
||
|
|
||
|
pub trait Keccak256<T> {
|
||
|
fn keccak256(&self) -> T where T: Sized;
|
||
|
}
|
||
|
|
||
|
impl Keccak256<[u8; 32]> for [u8] {
|
||
|
fn keccak256(&self) -> [u8; 32] {
|
||
|
let mut keccak = Keccak::new_keccak256();
|
||
|
let mut result = [0u8; 32];
|
||
|
keccak.update(self);
|
||
|
keccak.finalize(&mut result);
|
||
|
result
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// AES encryption
|
||
|
pub mod aes {
|
||
|
use rcrypto::blockmodes::CtrMode;
|
||
|
use rcrypto::aessafe::AesSafe128Encryptor;
|
||
|
use rcrypto::symmetriccipher::{Encryptor, Decryptor};
|
||
|
use rcrypto::buffer::{RefReadBuffer, RefWriteBuffer};
|
||
|
|
||
|
/// Encrypt a message
|
||
|
pub fn encrypt(k: &[u8], iv: &[u8], plain: &[u8], dest: &mut [u8]) {
|
||
|
let mut encryptor = CtrMode::new(AesSafe128Encryptor::new(k), iv.to_vec());
|
||
|
encryptor.encrypt(&mut RefReadBuffer::new(plain), &mut RefWriteBuffer::new(dest), true).expect("Invalid length or padding");
|
||
|
}
|
||
|
|
||
|
/// Decrypt a message
|
||
|
pub fn decrypt(k: &[u8], iv: &[u8], encrypted: &[u8], dest: &mut [u8]) {
|
||
|
let mut encryptor = CtrMode::new(AesSafe128Encryptor::new(k), iv.to_vec());
|
||
|
encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut RefWriteBuffer::new(dest), true).expect("Invalid length or padding");
|
||
|
}
|
||
|
}
|
||
|
|