ssi_di_sd_primitives/
lib.rs

1use std::ops::Deref;
2
3use getrandom::getrandom;
4pub use hmac::Hmac;
5use hmac::Mac;
6use serde::{Deserialize, Serialize};
7use sha2::{Sha256, Sha384};
8
9pub use ssi_core::{JsonPointer, JsonPointerBuf};
10
11pub type HmacSha256 = Hmac<Sha256>;
12pub type HmacSha384 = Hmac<Sha384>;
13
14#[derive(Debug, Clone, Copy)]
15pub enum ShaAny {
16    Sha256,
17    Sha384,
18}
19
20impl ShaAny {
21    pub fn into_key(self, key: Option<HmacShaAnyKey>) -> Result<HmacShaAnyKey, IntoHmacError> {
22        match (self, key) {
23            (Self::Sha256, Some(HmacShaAnyKey::Sha256(key))) => Ok(HmacShaAnyKey::Sha256(key)),
24            (Self::Sha384, Some(HmacShaAnyKey::Sha384(key))) => Ok(HmacShaAnyKey::Sha384(key)),
25            (_, Some(_)) => Err(IntoHmacError::IncompatibleKey),
26            (Self::Sha256, None) => {
27                let mut key = HmacSha256Key::default();
28                getrandom(&mut key).map_err(IntoHmacError::rng)?;
29                Ok(HmacShaAnyKey::Sha256(key))
30            }
31            (Self::Sha384, None) => {
32                let mut key = [0; 48];
33                getrandom(&mut key).map_err(IntoHmacError::rng)?;
34                Ok(HmacShaAnyKey::Sha384(key))
35            }
36        }
37    }
38
39    pub fn into_hmac(self, key: Option<HmacShaAnyKey>) -> Result<HmacShaAny, IntoHmacError> {
40        match (self, key) {
41            (Self::Sha256, Some(HmacShaAnyKey::Sha256(key))) => Ok(HmacShaAny::Sha256(
42                HmacSha256::new_from_slice(&key).unwrap(),
43            )),
44            (Self::Sha384, Some(HmacShaAnyKey::Sha384(key))) => Ok(HmacShaAny::Sha384(
45                HmacSha384::new_from_slice(&key).unwrap(),
46            )),
47            (_, Some(_)) => Err(IntoHmacError::IncompatibleKey),
48            (Self::Sha256, None) => {
49                let mut key = HmacSha256Key::default();
50                getrandom(&mut key).map_err(IntoHmacError::rng)?;
51                Ok(HmacShaAny::Sha256(
52                    HmacSha256::new_from_slice(&key).unwrap(),
53                ))
54            }
55            (Self::Sha384, None) => {
56                let mut key = [0; 48];
57                getrandom(&mut key).map_err(IntoHmacError::rng)?;
58                Ok(HmacShaAny::Sha384(
59                    HmacSha384::new_from_slice(&key).unwrap(),
60                ))
61            }
62        }
63    }
64
65    pub fn hash_all<I: IntoIterator>(&self, iter: I) -> ShaAnyBytes
66    where
67        I::Item: AsRef<[u8]>,
68    {
69        use sha2::Digest;
70        match self {
71            Self::Sha256 => ShaAnyBytes::Sha256(
72                iter.into_iter()
73                    .fold(Sha256::new(), |h, line| h.chain_update(line.as_ref()))
74                    .finalize()
75                    .into(),
76            ),
77            Self::Sha384 => ShaAnyBytes::Sha384(
78                iter.into_iter()
79                    .fold(Sha384::new(), |h, line| h.chain_update(line.as_ref()))
80                    .finalize()
81                    .into(),
82            ),
83        }
84    }
85}
86
87#[derive(Debug, thiserror::Error)]
88pub enum IntoHmacError {
89    #[error("incompatible key")]
90    IncompatibleKey,
91
92    #[error("random number generation failed: {0}")]
93    RandomGenerationFailed(String),
94}
95
96impl IntoHmacError {
97    fn rng(e: impl ToString) -> Self {
98        Self::RandomGenerationFailed(e.to_string())
99    }
100}
101
102pub enum HmacShaAny {
103    Sha256(HmacSha256),
104    Sha384(HmacSha384),
105}
106
107impl HmacShaAny {
108    pub fn update(&mut self, data: &[u8]) {
109        match self {
110            Self::Sha256(hmac) => hmac.update(data),
111            Self::Sha384(hmac) => hmac.update(data),
112        }
113    }
114
115    pub fn finalize_reset(&mut self) -> ShaAnyBytes {
116        match self {
117            Self::Sha256(hmac) => ShaAnyBytes::Sha256(hmac.finalize_reset().into_bytes().into()),
118            Self::Sha384(hmac) => ShaAnyBytes::Sha384(hmac.finalize_reset().into_bytes().into()),
119        }
120    }
121}
122
123#[derive(Debug, Clone, Copy)]
124pub enum ShaAnyBytes {
125    Sha256([u8; 32]),
126    Sha384([u8; 48]),
127}
128
129impl ShaAnyBytes {
130    pub fn as_slice(&self) -> &[u8] {
131        match self {
132            Self::Sha256(bytes) => bytes,
133            Self::Sha384(bytes) => bytes,
134        }
135    }
136}
137
138impl Deref for ShaAnyBytes {
139    type Target = [u8];
140
141    fn deref(&self) -> &Self::Target {
142        self.as_slice()
143    }
144}
145
146impl AsRef<[u8]> for ShaAnyBytes {
147    fn as_ref(&self) -> &[u8] {
148        self.as_slice()
149    }
150}
151
152#[derive(Debug, thiserror::Error)]
153#[error("invalid HMAC key")]
154pub struct InvalidHmacKey;
155
156pub type HmacSha256Key = [u8; 32];
157pub type HmacSha384Key = [u8; 48];
158
159#[derive(Debug, Clone, Copy)]
160pub enum HmacShaAnyKey {
161    Sha256(HmacSha256Key),
162    Sha384(HmacSha384Key),
163}
164
165impl HmacShaAnyKey {
166    pub fn from_bytes(bytes: &[u8]) -> Result<Self, InvalidHmacKey> {
167        match bytes.len() {
168            32 => Ok(Self::Sha256(bytes.try_into().unwrap())),
169            48 => Ok(Self::Sha384(bytes.try_into().unwrap())),
170            _ => Err(InvalidHmacKey),
171        }
172    }
173
174    pub fn as_slice(&self) -> &[u8] {
175        match self {
176            Self::Sha256(bytes) => bytes,
177            Self::Sha384(bytes) => bytes,
178        }
179    }
180
181    pub fn to_hmac(&self) -> HmacShaAny {
182        match self {
183            Self::Sha256(key) => HmacShaAny::Sha256(HmacSha256::new_from_slice(key).unwrap()),
184            Self::Sha384(key) => HmacShaAny::Sha384(HmacSha384::new_from_slice(key).unwrap()),
185        }
186    }
187
188    pub fn algorithm(&self) -> ShaAny {
189        match self {
190            Self::Sha256(_) => ShaAny::Sha256,
191            Self::Sha384(_) => ShaAny::Sha384,
192        }
193    }
194
195    pub fn into_sha256(self) -> Result<HmacSha256Key, Self> {
196        match self {
197            Self::Sha256(k) => Ok(k),
198            other => Err(other),
199        }
200    }
201}
202
203impl Deref for HmacShaAnyKey {
204    type Target = [u8];
205
206    fn deref(&self) -> &Self::Target {
207        self.as_slice()
208    }
209}
210
211impl Serialize for HmacShaAnyKey {
212    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
213    where
214        S: serde::Serializer,
215    {
216        hex::encode(self.as_slice()).serialize(serializer)
217    }
218}
219
220impl<'de> Deserialize<'de> for HmacShaAnyKey {
221    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
222    where
223        D: serde::Deserializer<'de>,
224    {
225        let hex_string = String::deserialize(deserializer)?;
226        let bytes = hex::decode(hex_string).map_err(serde::de::Error::custom)?;
227        HmacShaAnyKey::from_bytes(&bytes).map_err(serde::de::Error::custom)
228    }
229}
230
231pub mod canonicalize;
232pub mod group;
233pub mod select;
234pub mod skolemize;