#[cfg(feature = "cbindings")]
mod cbindings;
#[cfg(feature = "cbindings")]
pub use self::cbindings::libreauth_keygen;
use base64::Engine;
use base64::engine::general_purpose::STANDARD;
#[derive(Default)]
pub struct KeyBuilder {
size: usize,
key: Option<Vec<u8>>,
}
impl KeyBuilder {
pub fn new() -> Self {
Self {
size: 21,
key: None,
}
}
pub fn size(mut self, size: usize) -> Self {
if size != self.size {
self.size = size;
self.generate()
} else {
self
}
}
pub fn generate(mut self) -> Self {
if self.size == 0 {
panic!();
}
let mut key: Vec<u8> = vec![0; self.size];
if let Err(e) = getrandom::fill(key.as_mut_slice()) {
panic!("Fatal error: {}", e);
}
self.key = Some(key);
self
}
pub fn as_vec(&self) -> Vec<u8> {
self.key.clone().unwrap()
}
pub fn as_hex(&self) -> String {
hex::encode(self.key.clone().unwrap())
}
pub fn as_base32(&self) -> String {
base32::encode(
base32::Alphabet::Rfc4648 { padding: false },
self.key.clone().unwrap().as_slice(),
)
}
pub fn as_base64(&self) -> String {
STANDARD.encode(self.key.clone().unwrap().as_slice())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_uniqueness() {
let k1 = KeyBuilder::new().generate().as_vec();
let k2 = KeyBuilder::new().generate().as_vec();
assert!(k1 != k2);
}
#[test]
fn test_equality() {
let key = KeyBuilder::new().generate();
assert!(key.as_vec() == key.as_vec());
}
#[test]
fn test_size_change() {
let mut key = KeyBuilder::new().generate();
let k1 = key.as_vec();
key = key.size(42);
let k2 = key.as_vec();
assert!(k1 != k2);
}
#[test]
fn test_size_unchanged() {
let mut key = KeyBuilder::new().generate();
let k1 = key.as_vec();
key = key.size(21);
let k2 = key.as_vec();
assert!(k1 == k2);
}
#[test]
fn test_default_len() {
let key = KeyBuilder::new().generate().as_vec();
assert!(key.len() == 21);
}
#[test]
fn test_given_len() {
let lst: Vec<usize> = vec![1, 12, 21, 42, 128, 256];
for i in lst {
let key = KeyBuilder::new().size(i).generate().as_vec();
assert!(key.len() == i);
}
}
#[test]
#[should_panic]
fn test_null_len() {
KeyBuilder::new().size(0);
}
}