primitives/types/identifiers/
session_id.rs1use aes::cipher::generic_array::GenericArray;
2use derive_more::derive::{AsMut, AsRef, IntoIterator};
3use hybrid_array::Array;
4use serde::{Deserialize, Serialize};
5#[cfg(any(test, feature = "dev"))]
6use typenum::Unsigned;
7use typenum::U16;
8
9#[cfg(any(test, feature = "dev"))]
10use crate::random::{CryptoRngCore, Random};
11use crate::{
12 constants::CollisionResistanceBytes,
13 hashing::{self, Digest},
14 random::Seed,
15 transcripts::Transcript,
16};
17
18#[derive(Default, Copy, AsRef, AsMut, Clone, Serialize, Deserialize, PartialEq, IntoIterator)]
24#[into_iterator(owned, ref, ref_mut)]
25#[repr(transparent)]
26pub struct SessionId(Array<u8, CollisionResistanceBytes>);
27
28impl SessionId {
29 pub fn refresh_with<T: AsRef<[u8]> + ?Sized>(&mut self, tag: &T) {
31 self.0 = hashing::hash(&[self.as_ref(), tag.as_ref()]);
32 }
33
34 pub fn refresh_from<T: Transcript>(transcript: &mut T) -> SessionId {
36 SessionId(transcript.extract(b"new_session_id").into())
37 }
38}
39
40impl AsRef<[u8]> for SessionId {
43 fn as_ref(&self) -> &[u8] {
44 &self.0
45 }
46}
47
48impl std::ops::Deref for SessionId {
49 type Target = [u8; 32];
50
51 fn deref(&self) -> &[u8; 32] {
52 self.0.as_ref()
53 }
54}
55
56impl From<Digest> for SessionId {
57 fn from(value: Digest) -> Self {
58 SessionId(value)
59 }
60}
61
62impl From<SessionId> for [u8; 32] {
63 fn from(session_id: SessionId) -> [u8; 32] {
64 session_id.0.into()
65 }
66}
67
68impl<'sid> From<&'sid SessionId> for &'sid [u8; 32] {
69 fn from(session_id: &'sid SessionId) -> &'sid [u8; 32] {
70 (&session_id.0).into()
71 }
72}
73
74impl From<&SessionId> for u32 {
75 fn from(session_id: &SessionId) -> u32 {
76 u32::from_le_bytes(session_id.0[0..4].try_into().unwrap())
77 }
78}
79
80impl From<&SessionId> for [u8; 16] {
81 fn from(session_id: &SessionId) -> [u8; 16] {
82 let mut hash = [0; 16];
83 hashing::hash_into([session_id], &mut hash);
84 hash
85 }
86}
87
88impl From<&SessionId> for GenericArray<u8, U16> {
89 fn from(session_id: &SessionId) -> GenericArray<u8, U16> {
90 let mut hash = GenericArray::<u8, U16>::default();
91 hashing::hash_into([session_id], &mut hash);
92 hash
93 }
94}
95
96pub trait SessionIdGenerator {
102 fn generate_session_id_from(&self, seed: Seed) -> SessionId {
104 SessionId(seed.into())
105 }
106}
107
108#[cfg(any(test, feature = "dev"))]
109impl Random for SessionId {
110 fn random(mut rng: impl CryptoRngCore) -> Self {
111 let mut bytes = Array([0; CollisionResistanceBytes::USIZE]);
112 rng.fill_bytes(&mut bytes);
113 SessionId(bytes)
114 }
115}
116
117#[cfg(any(test, feature = "dev"))]
118impl SessionId {
119 pub fn from_hashed_seed(seed: &[u8]) -> SessionId {
121 let mut bytes = Array([0; CollisionResistanceBytes::USIZE]);
122 hashing::hash_into([seed], &mut bytes);
123 SessionId(bytes)
124 }
125}
126
127#[cfg(not(any(test, feature = "dev")))]
130impl std::fmt::Display for SessionId {
131 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132 write!(f, "SessionId({})", hex::encode(self.0))
133 }
134}
135
136#[cfg(not(any(test, feature = "dev")))]
137impl std::fmt::Debug for SessionId {
138 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139 write!(f, "SessionId({})", hex::encode(self.0))
140 }
141}
142
143#[cfg(any(test, feature = "dev"))]
144impl std::fmt::Display for SessionId {
145 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146 write!(f, "SessionId({}...)", &hex::encode(self.0)[0..6])
147 }
148}
149
150#[cfg(any(test, feature = "dev"))]
151impl std::fmt::Debug for SessionId {
152 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
153 write!(f, "SessionId({}...)", &hex::encode(self.0)[0..6])
154 }
155}