use chacha20poly1305::aead::bytes::{BufMut, BytesMut};
use core::fmt;
use nanorand::{BufferedRng, ChaCha8, Rng};
use zeroize::{Zeroize, ZeroizeOnDrop};
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct ZeroizeArray<const N: usize>([u8; N]);
impl<const N: usize> fmt::Debug for ZeroizeArray<N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"ZeroizeArray<const N: usize>({:?})",
&blake3::hash(&self.0)
)
}
}
impl<const N: usize> ZeroizeArray<N> {
pub fn new(value: [u8; N]) -> Self {
ZeroizeArray(value)
}
pub fn new_zeroed() -> Self {
ZeroizeArray([0u8; N])
}
pub fn fill_from_slice(&mut self, value: [u8; N]) -> &mut Self {
self.0.copy_from_slice(&value);
self
}
pub fn expose(&self) -> [u8; N] {
self.0
}
pub fn expose_borrowed(&self) -> &[u8; N] {
&self.0
}
pub fn clone(&self) -> ZeroizeArray<N> {
Self(self.0)
}
pub fn own(self) -> Self {
self
}
pub fn insert(&mut self, index: usize, value: u8) -> &mut Self {
self.0[index] = value;
self
}
pub fn csprng() -> Self {
let mut buffer = [0u8; N];
let mut rng = BufferedRng::new(ChaCha8::new());
rng.fill(&mut buffer);
let csprng = ZeroizeArray(buffer);
buffer.copy_from_slice(&[0u8; N]);
csprng
}
}
impl<const N: usize> Zeroize for ZeroizeArray<N> {
fn zeroize(&mut self) {
self.0[..].copy_from_slice(&[0u8; N]);
}
}
impl<const N: usize> Drop for ZeroizeArray<N> {
fn drop(&mut self) {
self.zeroize()
}
}
impl<const N: usize> ZeroizeOnDrop for ZeroizeArray<N> {}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct ZeroizeBytesArray<const N: usize>(BytesMut);
impl<const N: usize> ZeroizeBytesArray<N> {
pub fn new() -> Self {
ZeroizeBytesArray(BytesMut::with_capacity(N))
}
pub fn set(mut self, value: BytesMut) -> Self {
self.0.put(&value[..]);
self
}
pub fn with_additional_capacity(capacity: usize) -> Self {
ZeroizeBytesArray(BytesMut::with_capacity(N + capacity))
}
pub fn expose(&self) -> &BytesMut {
&self.0
}
pub fn clone(&self) -> ZeroizeBytesArray<N> {
Self(self.0.clone())
}
pub fn csprng() -> Self {
let mut buffer = [0u8; N];
let mut rng = BufferedRng::new(ChaCha8::new());
rng.fill(&mut buffer);
let mut bytes_buffer = BytesMut::with_capacity(N);
bytes_buffer.put(&buffer[..]);
buffer.copy_from_slice(&[0u8; N]);
ZeroizeBytesArray(bytes_buffer)
}
}
impl<const N: usize> fmt::Debug for ZeroizeBytesArray<N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"ZeroizeBytesArray<const N: usize>({:?})",
&blake3::hash(&self.0)
)
}
}
impl<const N: usize> Zeroize for ZeroizeBytesArray<N> {
fn zeroize(&mut self) {
self.0.clear()
}
}
impl<const N: usize> Drop for ZeroizeBytesArray<N> {
fn drop(&mut self) {
self.zeroize()
}
}
impl<const N: usize> ZeroizeOnDrop for ZeroizeBytesArray<N> {}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct ZeroizeBytes(BytesMut);
impl ZeroizeBytes {
pub fn new() -> Self {
ZeroizeBytes(BytesMut::new())
}
pub fn set(&mut self, value: BytesMut) -> &mut Self {
self.0.put(&value[..]);
self
}
pub fn new_with_capacity(capacity: usize) -> Self {
ZeroizeBytes(BytesMut::with_capacity(capacity))
}
pub fn expose(&self) -> &BytesMut {
&self.0
}
pub fn clone(&self) -> ZeroizeBytes {
Self(self.0.clone())
}
pub fn csprng<const BUFFER_SIZE: usize>() -> Self {
let mut buffer = [0u8; BUFFER_SIZE];
let mut rng = BufferedRng::new(ChaCha8::new());
rng.fill(&mut buffer);
let mut bytes_buffer = BytesMut::with_capacity(BUFFER_SIZE);
bytes_buffer.put(&buffer[..]);
buffer.copy_from_slice(&[0u8; BUFFER_SIZE]);
ZeroizeBytes(bytes_buffer)
}
}
impl fmt::Debug for ZeroizeBytes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ZeroizeBytes({:?})", &blake3::hash(&self.0))
}
}
impl Zeroize for ZeroizeBytes {
fn zeroize(&mut self) {
self.0.clear()
}
}
impl Drop for ZeroizeBytes {
fn drop(&mut self) {
self.zeroize()
}
}
impl ZeroizeOnDrop for ZeroizeBytes {}