#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(feature = "std")]
use std::vec::Vec;
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::vec::Vec;
use subtle::ConstantTimeEq;
use zeroize::Zeroizing;
#[cfg(feature = "std")]
use rand::{rngs::OsRng, RngCore};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum SecurityLevel {
L128,
L192,
L256,
Custom(u32),
}
impl SecurityLevel {
pub fn bits(&self) -> u32 {
match self {
SecurityLevel::L128 => 128,
SecurityLevel::L192 => 192,
SecurityLevel::L256 => 256,
SecurityLevel::Custom(bits) => *bits,
}
}
pub fn recommended_output_size(&self) -> usize {
(self.bits() / 4) as usize
}
pub fn meets_minimum(&self, minimum: SecurityLevel) -> bool {
self.bits() >= minimum.bits()
}
}
#[inline]
pub fn constant_time_eq(a: &[u8], b: &[u8]) -> bool {
if a.len() != b.len() {
return false;
}
a.ct_eq(b).into()
}
#[cfg(feature = "std")]
pub fn generate_salt(len: usize) -> Zeroizing<Vec<u8>> {
let mut salt = vec![0u8; len];
OsRng.fill_bytes(&mut salt);
Zeroizing::new(salt)
}
#[cfg(all(feature = "alloc", not(feature = "std"), not(target_arch = "wasm32")))]
pub fn generate_salt(len: usize) -> Zeroizing<Vec<u8>> {
let mut salt = vec![0u8; len];
Zeroizing::new(salt)
}
#[cfg(all(feature = "alloc", target_arch = "wasm32", not(feature = "std")))]
pub fn generate_salt(len: usize) -> Zeroizing<Vec<u8>> {
let mut salt = vec![0u8; len];
getrandom::getrandom(&mut salt).expect("Failed to generate random bytes");
Zeroizing::new(salt)
}