volaris_crypto/
primitives.rs

1//! This module contains all cryptographic primitives used by `volaris-crypto`
2use crate::protected::Protected;
3use rand::{prelude::ThreadRng, RngCore};
4
5/// This is the streaming block size
6///
7/// NOTE: Stream mode can be used to encrypt files less than this size, provided the implementation
8/// is correct
9pub const BLOCK_SIZE: usize = 1_048_576; // 1024*1024 bytes
10
11/// This is the length of the salt used for password hashing
12pub const SALT_LEN: usize = 16; // bytes
13
14pub const MASTER_KEY_LEN: usize = 32;
15pub const ENCRYPTED_MASTER_KEY_LEN: usize = 48;
16pub const ALGORITHMS_LEN: usize = 3;
17
18/// This is an `enum` containing all AEADs supported by `volaris-crypto`
19#[derive(Copy, Clone, PartialEq, Eq)]
20pub enum Algorithm {
21    Aes256Gcm,
22    XChaCha20Poly1305,
23    DeoxysII256,
24}
25
26/// This is an array containing all AEADs supported by `volaris-crypto`.
27///
28/// It can be used by and end-user application to show a list of AEADs that they may use
29pub static ALGORITHMS: [Algorithm; ALGORITHMS_LEN] = [
30    Algorithm::XChaCha20Poly1305,
31    Algorithm::Aes256Gcm,
32    Algorithm::DeoxysII256,
33];
34
35impl std::fmt::Display for Algorithm {
36    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
37        match self {
38            Algorithm::Aes256Gcm => write!(f, "AES-256-GCM"),
39            Algorithm::XChaCha20Poly1305 => write!(f, "XChaCha20-Poly1305"),
40            Algorithm::DeoxysII256 => write!(f, "Deoxys-II-256"),
41        }
42    }
43}
44
45/// This defines the possible modes used for encrypting/decrypting
46#[derive(PartialEq, Eq)]
47pub enum Mode {
48    MemoryMode,
49    StreamMode,
50}
51
52impl std::fmt::Display for Mode {
53    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
54        match self {
55            Mode::MemoryMode => write!(f, "Memory Mode"),
56            Mode::StreamMode => write!(f, "Stream Mode"),
57        }
58    }
59}
60
61/// This can be used to generate a nonce for encryption
62/// It requires both the algorithm and the mode, so it can correctly determine the nonce length
63/// This nonce can be passed directly to `EncryptionStreams::initialize()`
64///
65/// # Examples
66///
67/// ```rust
68/// # use Volaris_corecrypto::primitives::*;
69/// let nonce = gen_nonce(&Algorithm::XChaCha20Poly1305, &Mode::StreamMode);
70/// ```
71///
72#[must_use]
73pub fn gen_nonce(algorithm: &Algorithm, mode: &Mode) -> Vec<u8> {
74    let nonce_len = get_nonce_len(algorithm, mode);
75    let mut nonce = vec![0u8; nonce_len];
76    ThreadRng::default().fill_bytes(&mut nonce);
77    nonce
78}
79
80/// This function calculates the length of the nonce, depending on the data provided
81///
82/// Stream mode nonces are 4 bytes less than their "memory" mode counterparts, due to `aead::StreamLE31`
83///
84/// `StreamLE31` contains a 31-bit little endian counter, and a 1-bit "last block" flag, stored as the last 4 bytes of the nonce, this is done to prevent nonce-reuse
85#[must_use]
86pub fn get_nonce_len(algorithm: &Algorithm, mode: &Mode) -> usize {
87    let mut nonce_len = match algorithm {
88        Algorithm::Aes256Gcm => 12,
89        Algorithm::XChaCha20Poly1305 => 24,
90        Algorithm::DeoxysII256 => 15,
91    };
92
93    if mode == &Mode::StreamMode {
94        nonce_len -= 4;
95    }
96
97    nonce_len
98}
99
100/// Generates a new protected master key of the specified `MASTER_KEY_LEN`.
101///
102/// This can be used to generate a master key for encryption.
103/// It uses `ThreadRng` to securely generate completely random bytes, with extra protection
104/// from some side-channel attacks
105///
106/// # Examples
107///
108/// ```rust
109/// # use Volaris_corecrypto::primitives::*;
110/// let master_key = gen_master_key();
111/// ```
112///
113#[must_use]
114pub fn gen_master_key() -> Protected<[u8; MASTER_KEY_LEN]> {
115    let mut master_key = [0u8; MASTER_KEY_LEN];
116    ThreadRng::default().fill_bytes(&mut master_key);
117    Protected::new(master_key)
118}
119
120/// Generates a salt, of the specified `SALT_LEN`
121///
122/// This salt can be directly passed to `argon2id_hash()` or `balloon_hash()`
123///
124/// # Examples
125///
126/// ```rust
127/// # use Volaris_corecrypto::primitives::*;
128/// let salt = gen_salt();
129/// ```
130///
131#[must_use]
132pub fn gen_salt() -> [u8; SALT_LEN] {
133    let mut salt = [0u8; SALT_LEN];
134    ThreadRng::default().fill_bytes(&mut salt);
135    salt
136}