1use alloc::vec::Vec;
4
5use zeroize::{Zeroize, ZeroizeOnDrop};
6
7use crate::tags::{TAG_NONC, TAG_PAD};
8
9const MIN_REQUEST_LEN: usize = 1024;
11
12#[derive(Zeroize, ZeroizeOnDrop)]
18pub struct Nonce([u8; 64]);
19
20impl core::fmt::Debug for Nonce {
21 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
22 f.debug_struct("Nonce").finish_non_exhaustive()
23 }
24}
25
26impl Nonce {
27 #[must_use]
32 pub const fn new(bytes: [u8; 64]) -> Self {
33 Self(bytes)
34 }
35
36 #[must_use]
38 pub const fn as_bytes(&self) -> &[u8; 64] {
39 &self.0
40 }
41
42 #[cfg(feature = "std")]
48 pub fn random() -> Result<Self, crate::Error> {
49 let mut bytes = [0u8; 64];
50 crate::crypto::fill_random(&mut bytes).map_err(|_err| crate::Error::RandomUnavailable)?;
51 Ok(Self(bytes))
52 }
53}
54
55#[must_use]
57pub fn build_request(nonce: &Nonce) -> Vec<u8> {
58 let mut req = Vec::with_capacity(MIN_REQUEST_LEN);
59 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());
62 req.extend_from_slice(&TAG_PAD.to_le_bytes());
63 req.extend_from_slice(nonce.as_bytes());
64 req.resize(MIN_REQUEST_LEN, 0);
65 req
66}
67
68#[cfg(feature = "std")]
74pub fn build_request_random() -> Result<(Nonce, Vec<u8>), crate::Error> {
75 let nonce = Nonce::random()?;
76 let req = build_request(&nonce);
77 Ok((nonce, req))
78}
79
80#[cfg(test)]
81mod tests {
82 use super::{Nonce, build_request};
83
84 #[test]
85 fn builds_padded_request() {
86 let nonce = Nonce::new([0x42; 64]);
87 let req = build_request(&nonce);
88 assert_eq!(req.len(), 1024);
89 assert_eq!(&req[16..80], nonce.as_bytes());
90 }
91}