vault-core 0.1.1

Password based encryption/decryption
Documentation
use argon2::Argon2;
use rand::rngs::OsRng;
use rand::RngCore;
use zeroize::Zeroize;

use crate::err::KeyGenerationError;

pub(crate) struct GeneratedKey {
    pub key: Vec<u8>,
    pub salt: Vec<u8>,
    pub nonce: Vec<u8>,
}

impl GeneratedKey {
    pub fn cleanup(&mut self) {
        self.key.zeroize();
        self.salt.zeroize();
        self.nonce.zeroize();
    }
}

pub(crate) fn generate_key(password: &str) -> Result<GeneratedKey, KeyGenerationError> {
    let salt = generate_random_salt(32);
    let nonce = generate_random_nonce(19);

    derive_key(password, salt, nonce)
}

pub(crate) fn derive_key(
    password: &str,
    salt: Vec<u8>,
    nonce: Vec<u8>,
) -> Result<GeneratedKey, KeyGenerationError> {
    let argon = setup_argon();
    let mut key_buffer = vec![0u8; 32];

    argon
        .hash_password_into(password.as_bytes(), &salt, &mut key_buffer)
        .map_err(|_| KeyGenerationError {})?;

    Ok(GeneratedKey {
        salt,
        nonce,
        key: key_buffer,
    })
}

fn generate_random_salt(size: usize) -> Vec<u8> {
    generate_random_buffer(size)
}

fn generate_random_nonce(size: usize) -> Vec<u8> {
    generate_random_buffer(size)
}

fn generate_random_buffer(size: usize) -> Vec<u8> {
    let mut buffer = vec![0u8; size];
    OsRng.fill_bytes(&mut buffer);

    buffer
}

fn setup_argon() -> Argon2<'static> {
    Argon2::default()
}