ssi_di_sd_primitives/
lib.rs1use 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;