summaryrefslogtreecommitdiff
path: root/src/vapid/history.rs
blob: 42f062b2ca22baa11176b9e7022abbc3896132fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
use p256::ecdsa::{SigningKey, VerifyingKey};
use rand::thread_rng;

use super::event::{Changed, Event};
use crate::{clock::DateTime, event::Instant};

#[derive(Debug)]
pub struct History {
    pub key: VerifyingKey,
    pub changed: Instant,
}

// Lifecycle interface
impl History {
    pub fn begin(changed: &Instant) -> (Self, SigningKey) {
        let key = SigningKey::random(&mut thread_rng());
        (
            Self {
                key: VerifyingKey::from(&key),
                changed: *changed,
            },
            key,
        )
    }

    // `self` _is_ unused here, clippy is right about that. This choice is deliberate, however - it
    // makes it harder to inadvertently reuse a rotated key via its history, and it makes the
    // lifecycle interface more obviously consistent between this and other History types.
    #[allow(clippy::unused_self)]
    pub fn rotate(self, changed: &Instant) -> (Self, SigningKey) {
        Self::begin(changed)
    }
}

// State interface
impl History {
    pub fn older_than(&self, when: DateTime) -> bool {
        self.changed.at < when
    }
}

// Events interface
impl History {
    pub fn events(&self) -> impl Iterator<Item = Event> + Clone {
        [self.changed()].into_iter()
    }

    fn changed(&self) -> Event {
        Changed {
            key: self.key,
            instant: self.changed,
        }
        .into()
    }
}