1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
use hmac::Hmac;
use pbkdf2::pbkdf2;
use rand_core::{OsRng, RngCore};
use sha2::Sha256;
/// `Key` holds a public key and a salt value.
/// This struct is specifically designed for use in symmetric encryption,
/// and is compatible with multiple encryption algorithms.
pub struct Key<const P: usize, const S: usize> {
/// Public key.
pub pubk: [u8; P],
/// Salt value.
pub salt: [u8; S],
}
impl<const P: usize, const S: usize> Key<P, S> {
/// Constructs a new `Key` using a specified password and a number of rounds for key derivation.
/// The method automatically generates a random salt for each key.
///
/// # Arguments
/// * `password` - A byte slice representing the password from which the key will be derived.
/// * `rounds` - The number of iterations used in the PBKDF2 key derivation function.
///
/// # Returns
/// An instance of `Key` containing the derived public key and the generated salt.
///
/// # Panics
/// Panics if the key derivation fails.
pub fn new(password: &[u8], rounds: u32) -> Self {
// Generate a random salt value
let salt = random_bytes::<S>();
// Derive the public key using PBKDF2 algorithm
let mut pubk = [0; P];
if pbkdf2::<Hmac<Sha256>>(password, &salt, rounds, &mut pubk).is_err() {
panic!("Key derivation failed")
}
Self { pubk, salt }
}
/// Constructs a new `Key` using a specified password, a provided salt, and a number of rounds for key derivation.
///
/// # Arguments
/// * `password` - A byte slice representing the password from which the key will be derived.
/// * `salt` - An array representing the salt to be used in the key derivation.
/// * `rounds` - The number of iterations used in the PBKDF2 key derivation function.
///
/// # Returns
/// An instance of `Key` containing the derived public key and the provided salt.
///
/// # Panics
/// Panics if the key derivation fails.
pub fn with_salt(password: &[u8], salt: [u8; S], rounds: u32) -> Self {
// Derive the public key using PBKDF2 algorithm with the provided salt
let mut pubk = [0; P];
if pbkdf2::<Hmac<Sha256>>(password, &salt, rounds, &mut pubk).is_err() {
panic!("Key derivation failed")
}
Self { pubk, salt }
}
}
/// Generates a random byte array of a specified size.
pub fn random_bytes<const S: usize>() -> [u8; S] {
let mut bytes = [0; S];
OsRng.fill_bytes(&mut bytes);
bytes
}