primitives/types/identifiers/
session_id.rs1use 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#[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 pub fn refresh(&mut self) {
30 self.0 = hashing::hash(&[self.as_ref(), b"sid_refresh"]);
31 }
32
33 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
42impl 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
90pub trait SessionIdGenerator {
93 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 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#[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}