aranya_crypto/
id.rs

1//! Crypto extensions and other related items for IDs.
2
3#![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
13/// Extension trait for IDs.
14pub trait IdExt: Sized {
15    /// Derives an ID from the hash of some data.
16    fn new<'a, CS: CipherSuite>(
17        tag: &'static [u8],
18        context: impl IntoIterator<Item = &'a [u8]>,
19    ) -> Self;
20
21    /// Creates a random ID.
22    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        // id = H("ID-v1" || suites || data || tag)
34        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
47/// An object with a unique identifier.
48pub trait Identified {
49    /// Uniquely identifies the object.
50    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    /// Uniquely identifies the object.
64    fn id(&self) -> Result<Self::Id, IdError>;
65}
66
67/// An error that may occur when accessing an Id
68#[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}