holochain_nonce/
lib.rs

1use holochain_secure_primitive::secure_primitive;
2use holochain_timestamp::Timestamp;
3use std::{error::Error, time::Duration};
4
5/// 256 Bit generic nonce.
6#[derive(Clone, Copy)]
7pub struct Nonce256Bits([u8; 32]);
8secure_primitive!(Nonce256Bits, 32);
9
10impl Nonce256Bits {
11    pub fn into_inner(self) -> [u8; 32] {
12        self.0
13    }
14}
15
16/// Rather arbitrary but we expire nonces after 5 mins.
17pub const FRESH_NONCE_EXPIRES_AFTER: Duration = Duration::from_secs(60 * 5);
18
19/// Generate a fresh nonce.
20///
21/// The nonce will be valid from the given `now` timestamp until `now` + [FRESH_NONCE_EXPIRES_AFTER].
22/// A new nonce and the expiry are returned as a tuple.
23///
24/// Note: the expiry isn't managed by this function. It's up to the caller to enforce the expiry
25/// time of the nonce.
26pub fn fresh_nonce(
27    now: Timestamp,
28) -> Result<(Nonce256Bits, Timestamp), Box<dyn Error + std::marker::Send + Sync>> {
29    let mut bytes = [0; 32];
30    getrandom::getrandom(&mut bytes)?;
31    let nonce = Nonce256Bits::from(bytes);
32    let expires: Timestamp = (now + FRESH_NONCE_EXPIRES_AFTER)?;
33    Ok((nonce, expires))
34}
35
36#[cfg(test)]
37pub mod test {
38    use holochain_timestamp::Timestamp;
39
40    use crate::{fresh_nonce, FRESH_NONCE_EXPIRES_AFTER};
41
42    #[test]
43    fn test_fresh_nonce() {
44        let now = Timestamp::now();
45        let (nonce, expires) = fresh_nonce(now).unwrap();
46        let (nonce_2, expires_2) = fresh_nonce(now).unwrap();
47        assert!(nonce != nonce_2);
48        assert_eq!(expires, expires_2);
49        assert_eq!(expires, (now + FRESH_NONCE_EXPIRES_AFTER).unwrap());
50    }
51}