1#![forbid(unsafe_code)]
4
5use core::iter;
6
7pub use aranya_id::*;
8use buggy::Bug;
9use spideroak_crypto::{csprng::Csprng, signer::PkError};
10
11use crate::ciphersuite::{CipherSuite, CipherSuiteExt as _};
12
13pub trait IdExt: Sized {
15 fn new<'a, CS: CipherSuite>(
17 tag: &'static [u8],
18 context: impl IntoIterator<Item = &'a [u8]>,
19 ) -> Self;
20
21 fn random<R: Csprng>(rng: &mut R) -> Self;
23}
24
25impl<I> IdExt for I
26where
27 [u8; 32]: Into<I>,
28{
29 fn new<'a, CS: CipherSuite>(
30 tag: &'static [u8],
31 data: impl IntoIterator<Item = &'a [u8]>,
32 ) -> Self {
33 CS::tuple_hash(b"ID-v1", data.into_iter().chain(iter::once(tag)))
35 .into_array()
36 .into_array()
37 .into()
38 }
39
40 fn random<R: Csprng>(rng: &mut R) -> Self {
41 let mut b = [0u8; 32];
42 rng.fill_bytes(&mut b);
43 b.into()
44 }
45}
46
47pub trait Identified {
49 type Id: Copy
51 + Clone
52 + core::fmt::Display
53 + core::fmt::Debug
54 + core::hash::Hash
55 + Eq
56 + PartialEq
57 + Ord
58 + PartialOrd
59 + serde::Serialize
60 + serde::de::DeserializeOwned
61 + AsRef<BaseId>;
62
63 fn id(&self) -> Result<Self::Id, IdError>;
65}
66
67#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
69#[error("{0}")]
70pub struct IdError(IdErrorRepr);
71
72impl IdError {
73 pub(crate) const fn new(msg: &'static str) -> Self {
74 Self(IdErrorRepr::Msg(msg))
75 }
76}
77
78impl From<Bug> for IdError {
79 #[inline]
80 fn from(err: Bug) -> Self {
81 Self(IdErrorRepr::Bug(err))
82 }
83}
84
85impl From<PkError> for IdError {
86 fn from(err: PkError) -> Self {
87 Self::new(err.msg())
88 }
89}
90
91#[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
92enum IdErrorRepr {
93 #[error("{0}")]
94 Bug(Bug),
95 #[error("{0}")]
96 Msg(&'static str),
97}