use alloc::vec::Vec;
use zeroize::{Zeroize, ZeroizeOnDrop};
use crate::tags::{TAG_NONC, TAG_PAD};
const MIN_REQUEST_LEN: usize = 1024;
#[derive(Zeroize, ZeroizeOnDrop)]
pub struct Nonce([u8; 64]);
impl core::fmt::Debug for Nonce {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Nonce").finish_non_exhaustive()
}
}
impl Nonce {
#[must_use]
pub const fn new(bytes: [u8; 64]) -> Self {
Self(bytes)
}
#[must_use]
pub const fn as_bytes(&self) -> &[u8; 64] {
&self.0
}
#[cfg(feature = "std")]
pub fn random() -> Result<Self, crate::Error> {
let mut bytes = [0u8; 64];
crate::crypto::fill_random(&mut bytes).map_err(|_err| crate::Error::RandomUnavailable)?;
Ok(Self(bytes))
}
}
#[must_use]
pub fn build_request(nonce: &Nonce) -> Vec<u8> {
let mut req = Vec::with_capacity(MIN_REQUEST_LEN);
req.extend_from_slice(&2u32.to_le_bytes()); req.extend_from_slice(&64u32.to_le_bytes()); req.extend_from_slice(&TAG_NONC.to_le_bytes());
req.extend_from_slice(&TAG_PAD.to_le_bytes());
req.extend_from_slice(nonce.as_bytes());
req.resize(MIN_REQUEST_LEN, 0);
req
}
#[cfg(feature = "std")]
pub fn build_request_random() -> Result<(Nonce, Vec<u8>), crate::Error> {
let nonce = Nonce::random()?;
let req = build_request(&nonce);
Ok((nonce, req))
}
#[cfg(test)]
mod tests {
use super::{Nonce, build_request};
#[test]
fn builds_padded_request() {
let nonce = Nonce::new([0x42; 64]);
let req = build_request(&nonce);
assert_eq!(req.len(), 1024);
assert_eq!(&req[16..80], nonce.as_bytes());
}
}