coven_crypto/
confirmation_number.rs1use crate::{cipher, derivation::CONFIRMATION_NUMBER, MemberPublicKeys};
4use coven_foundation::id_source::InviteId;
5use sha2::{Digest, Sha256};
6use std::fmt;
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
13pub struct ConfirmationNumber(pub u32);
14
15impl ConfirmationNumber {
16 pub fn of(invite: InviteId, keys: &MemberPublicKeys) -> Self {
19 let mut encoded = [0; 64];
20 encoded[..32].copy_from_slice(keys.signing.as_bytes());
21 encoded[32..].copy_from_slice(keys.sealing.as_bytes());
22 let digest =
23 Sha256::digest(cipher::context(&[CONFIRMATION_NUMBER, invite.0.as_bytes(), &encoded]));
24 let first = u64::from_be_bytes(digest[..8].try_into().expect("8 of 32 bytes"));
25 Self(u32::try_from(first % 1_000_000).expect("below 1,000,000"))
26 }
27}
28
29impl fmt::Display for ConfirmationNumber {
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 write!(f, "{:03} {:03}", self.0 / 1000, self.0 % 1000)
32 }
33}
34
35#[cfg(test)]
36#[path = "confirmation_number_tests.rs"]
37mod tests;