eck 0.0.3

A fast, simple file & folder encryption manager, written in Rust
use crate::errors::EnkryptitError;
/// Primitives for **Enkryptit!** : low-level functions called by `encryption_flow`
use chacha20poly1305::{
    XChaCha20Poly1305, XNonce,
    aead::{AeadInPlace, OsRng},
};
use rand::RngCore;

/// Public function that encrypts a given chunk in place.
/// \
/// We derivate a new nonce at each step, that's why we need to know value of the step.
/// \
/// The algorithm used is `XChaCha20Poly1305`, because it is efficient and studied.
pub fn encrypt_chunk(
    data: &mut Vec<u8>,
    nonce: &[u8; 24],
    cipher: &XChaCha20Poly1305,
    step: u64,
) -> Result<(), EnkryptitError> {
    let new_nonce = derive_nonce(nonce, step);
    cipher.encrypt_in_place(XNonce::from_slice(&new_nonce), b"", data)?;
    Ok(())
}

/// Function that derives the current nonce, from the master nonce (randomly generated bytes) and the current step.
/// \
/// The new nonce is :
///
/// new_nonce[0..16]  = master_nonce[0..16]
/// \
/// new_nonce[16..24] = step.to_le_bytes() (8 bytes, little-endian)
pub fn derive_nonce(master_nonce: &[u8; 24], step: u64) -> [u8; 24] {
    let mut nonce = *master_nonce;
    nonce[16..24].copy_from_slice(&step.to_le_bytes());
    nonce
}

/// Public function that decrypts a chunk in-place.
/// \
/// It derivates the nonce (given the `master_nonce`, which is a buffer of randomly generated bytes, and the step) before decrypting in-place.
pub fn decrypt_chunk(
    data: &mut Vec<u8>,
    cipher: &XChaCha20Poly1305,
    nonce: &[u8; 24],
    step: u64,
) -> Result<(), EnkryptitError> {
    let new_nonce = derive_nonce(nonce, step);
    cipher.decrypt_in_place(XNonce::from_slice(&new_nonce), b"", data)?;
    Ok(())
}

/// Public function that generates the `master nonce`, using `OsRng`.
pub fn generate_nonce() -> [u8; 24] {
    let mut rng = OsRng;
    let mut nonce_bytes = [0u8; 24];
    rng.fill_bytes(&mut nonce_bytes);
    nonce_bytes
}