primitives/types/identifiers/
session_id.rs

1use aes::cipher::generic_array::GenericArray;
2use derive_more::derive::{AsMut, AsRef, IntoIterator};
3use hybrid_array::Array;
4#[cfg(any(test, feature = "dev"))]
5use rand::{distributions::Standard, prelude::Distribution, Rng};
6use serde::{Deserialize, Serialize};
7#[cfg(any(test, feature = "dev"))]
8use typenum::Unsigned;
9use typenum::U16;
10
11use crate::{
12    constants::CollisionResistanceBytes,
13    hashing::{self, Digest},
14    random::{derive_rng::DeriveRng, Seed},
15    transcripts::{protocol_transcript::ProtocolTranscript, Transcript},
16};
17
18/// The type of a session identifier, commonly used by protocols to achieve UC
19/// security in the CRS model. It should be unique for each protocol execution.
20/// We make it be random by:
21/// - Sampling an original Session ID via a distributed protocol (or via local sampling in tests).
22/// - Refreshing it upon each protocol execution by mixig it with the protocol transcript.
23#[derive(Default, Copy, AsRef, AsMut, Clone, Serialize, Deserialize, PartialEq, IntoIterator)]
24#[into_iterator(owned, ref, ref_mut)]
25pub struct SessionId(Array<u8, CollisionResistanceBytes>);
26
27impl SessionId {
28    /// Refreshes the session ID on its own.
29    pub fn refresh(&mut self) {
30        self.0 = hashing::hash(&[self.as_ref(), b"sid_refresh"]);
31    }
32
33    /// Refreshes the session ID by extracting randomness from a given transcript.
34    pub fn refresh_from<T: Transcript>(&mut self, transcript: &mut ProtocolTranscript<T>) {
35        transcript.append(self.0);
36        transcript.extract(b"new_session_id", &mut self.0);
37    }
38}
39
40impl DeriveRng for SessionId {}
41
42// ---------- Conversions ----------- //
43
44impl AsRef<[u8]> for SessionId {
45    fn as_ref(&self) -> &[u8] {
46        &self.0
47    }
48}
49
50impl From<Digest> for SessionId {
51    fn from(value: Digest) -> Self {
52        SessionId(value)
53    }
54}
55
56impl From<SessionId> for [u8; 32] {
57    fn from(session_id: SessionId) -> [u8; 32] {
58        session_id.0.into()
59    }
60}
61
62impl<'sid> From<&'sid SessionId> for &'sid [u8; 32] {
63    fn from(session_id: &'sid SessionId) -> &'sid [u8; 32] {
64        (&session_id.0).into()
65    }
66}
67
68impl From<&SessionId> for u32 {
69    fn from(session_id: &SessionId) -> u32 {
70        u32::from_le_bytes(session_id.0[0..4].try_into().unwrap())
71    }
72}
73
74impl From<&SessionId> for [u8; 16] {
75    fn from(session_id: &SessionId) -> [u8; 16] {
76        let mut hash = [0; 16];
77        hashing::hash_into([session_id], &mut hash);
78        hash
79    }
80}
81
82impl From<&SessionId> for GenericArray<u8, U16> {
83    fn from(session_id: &SessionId) -> GenericArray<u8, U16> {
84        let mut hash = GenericArray::<u8, U16>::default();
85        hashing::hash_into([session_id], &mut hash);
86        hash
87    }
88}
89
90// ------ Generation ------ //
91
92pub trait SessionIdGenerator {
93    /// Generates a new session ID from a given seed.
94    fn generate_session_id_from(&self, seed: Seed) -> SessionId {
95        SessionId(seed.into())
96    }
97}
98
99#[cfg(any(test, feature = "dev"))]
100impl Distribution<SessionId> for Standard {
101    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> SessionId {
102        let mut bytes = Array([0; CollisionResistanceBytes::USIZE]);
103        rng.fill_bytes(&mut bytes);
104        SessionId(bytes)
105    }
106}
107
108#[cfg(any(test, feature = "dev"))]
109impl SessionId {
110    /// Generates a new session ID by hashing the given seed.
111    pub fn from_hashed_seed(seed: &[u8]) -> SessionId {
112        let mut bytes = Array([0; CollisionResistanceBytes::USIZE]);
113        hashing::hash_into([seed], &mut bytes);
114        SessionId(bytes)
115    }
116}
117
118// --------- Display -------- //
119
120#[cfg(not(any(test, feature = "dev")))]
121impl std::fmt::Display for SessionId {
122    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
123        write!(f, "SessionId({})", hex::encode(self.0))
124    }
125}
126
127#[cfg(not(any(test, feature = "dev")))]
128impl std::fmt::Debug for SessionId {
129    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130        write!(f, "SessionId({})", hex::encode(self.0))
131    }
132}
133
134#[cfg(any(test, feature = "dev"))]
135impl std::fmt::Display for SessionId {
136    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137        write!(f, "SessionId({}...)", &hex::encode(self.0)[0..6])
138    }
139}
140
141#[cfg(any(test, feature = "dev"))]
142impl std::fmt::Debug for SessionId {
143    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
144        write!(f, "SessionId({}...)", &hex::encode(self.0)[0..6])
145    }
146}