1use core::fmt;
2use serde::{Deserialize, Serialize};
3use ssi_crypto::{
4 algorithm::{ES256OrES384, SignatureAlgorithmInstance, SignatureAlgorithmType},
5 UnsupportedAlgorithm,
6};
7
8macro_rules! algorithms {
9 ($(
10 $(#[doc = $doc:tt])*
11 $(#[doc($doc_tag:ident)])?
12 $(#[serde $serde:tt])?
13 $id:ident: $name:literal
14 ),*) => {
15 #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Hash, Eq)]
17 pub enum Algorithm {
18 $(
19 $(#[doc = $doc])*
20 $(#[doc($doc_tag)])?
21 $(#[serde $serde])?
22 #[serde(rename = $name)]
23 $id,
24 )*
25 #[serde(alias = "None", rename = "none")]
30 None
31 }
32
33 impl Algorithm {
34 pub fn as_str(&self) -> &'static str {
35 match self {
36 $(
37 Self::$id => $name,
38 )*
39 Self::None => "none"
40 }
41 }
42
43 pub fn into_str(self) -> &'static str {
44 match self {
45 $(
46 Self::$id => $name,
47 )*
48 Self::None => "none"
49 }
50 }
51 }
52
53 impl From<Algorithm> for ssi_crypto::Algorithm {
54 fn from(a: Algorithm) -> Self {
55 match a {
56 $(Algorithm::$id => Self::$id,)*
57 Algorithm::None => Self::None
58 }
59 }
60 }
61
62 impl From<Algorithm> for ssi_crypto::AlgorithmInstance {
63 fn from(a: Algorithm) -> Self {
64 match a {
65 $(Algorithm::$id => Self::$id,)*
66 Algorithm::None => Self::None
67 }
68 }
69 }
70
71 $(
72 impl From<ssi_crypto::algorithm::$id> for Algorithm {
73 fn from(_: ssi_crypto::algorithm::$id) -> Self {
74 Self::$id
75 }
76 }
77
78 impl TryFrom<Algorithm> for ssi_crypto::algorithm::$id {
79 type Error = UnsupportedAlgorithm;
80
81 fn try_from(value: Algorithm) -> Result<Self, Self::Error> {
82 match value {
83 Algorithm::$id => Ok(Self),
84 other => Err(UnsupportedAlgorithm(other.into()))
85 }
86 }
87 }
88 )*
89
90 impl TryFrom<ssi_crypto::Algorithm> for Algorithm {
91 type Error = UnsupportedAlgorithm;
92
93 fn try_from(a: ssi_crypto::Algorithm) -> Result<Self, Self::Error> {
94 match a {
95 $(ssi_crypto::Algorithm::$id => Ok(Self::$id),)*
96 ssi_crypto::Algorithm::None => Ok(Self::None),
97 other => Err(UnsupportedAlgorithm(other))
98 }
99 }
100 }
101
102 impl TryFrom<ssi_crypto::AlgorithmInstance> for Algorithm {
103 type Error = UnsupportedAlgorithm;
104
105 fn try_from(a: ssi_crypto::AlgorithmInstance) -> Result<Self, Self::Error> {
106 match a {
107 $(ssi_crypto::AlgorithmInstance::$id => Ok(Self::$id),)*
108 ssi_crypto::AlgorithmInstance::None => Ok(Self::None),
109 other => Err(UnsupportedAlgorithm(other.algorithm()))
110 }
111 }
112 }
113 };
114}
115
116algorithms! {
117 HS256: "HS256",
121
122 HS384: "HS384",
126
127 HS512: "HS512",
131
132 RS256: "RS256",
136
137 RS384: "RS384",
141
142 RS512: "RS512",
146
147 PS256: "PS256",
151
152 PS384: "PS384",
156
157 PS512: "PS512",
161
162 EdDSA: "EdDSA",
170
171 EdBlake2b: "EdBlake2b", ES256: "ES256",
178
179 ES384: "ES384",
183
184 ES256K: "ES256K",
188
189 ES256KR: "ES256K-R",
197
198 ESKeccakK: "ESKeccakK",
202
203 ESKeccakKR: "ESKeccakKR",
207
208 ESBlake2b: "ESBlake2b",
210
211 ESBlake2bK: "ESBlake2bK",
213
214 #[doc(hidden)]
215 AleoTestnet1Signature: "AleoTestnet1Signature"
216}
217
218impl Algorithm {
219 pub fn is_compatible_with(&self, other: Self) -> bool {
224 match self {
225 Self::ES256K | Self::ES256KR | Self::ESKeccakK | Self::ESKeccakKR => matches!(
226 other,
227 Self::ES256K | Self::ES256KR | Self::ESKeccakK | Self::ESKeccakKR
228 ),
229 a => *a == other,
230 }
231 }
232}
233
234impl SignatureAlgorithmType for Algorithm {
235 type Instance = Self;
236}
237
238impl SignatureAlgorithmInstance for Algorithm {
239 type Algorithm = Self;
240
241 fn algorithm(&self) -> Self {
242 *self
243 }
244}
245
246impl Default for Algorithm {
247 fn default() -> Self {
248 Self::None
249 }
250}
251
252impl AsRef<str> for Algorithm {
253 fn as_ref(&self) -> &str {
254 self.as_str()
255 }
256}
257
258impl fmt::Display for Algorithm {
259 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
260 self.as_str().fmt(f)
261 }
262}
263
264impl From<ssi_crypto::algorithm::AnyBlake2b> for Algorithm {
265 fn from(value: ssi_crypto::algorithm::AnyBlake2b) -> Self {
266 match value {
267 ssi_crypto::algorithm::AnyBlake2b::ESBlake2b => Self::ESBlake2b,
268 ssi_crypto::algorithm::AnyBlake2b::ESBlake2bK => Self::ESBlake2bK,
269 ssi_crypto::algorithm::AnyBlake2b::EdBlake2b => Self::EdBlake2b,
270 }
271 }
272}
273
274impl TryFrom<Algorithm> for ssi_crypto::algorithm::AnyBlake2b {
275 type Error = UnsupportedAlgorithm;
276
277 fn try_from(value: Algorithm) -> Result<Self, Self::Error> {
278 match value {
279 Algorithm::ESBlake2b => Ok(Self::ESBlake2b),
280 Algorithm::ESBlake2bK => Ok(Self::ESBlake2bK),
281 Algorithm::EdBlake2b => Ok(Self::EdBlake2b),
282 other => Err(UnsupportedAlgorithm(other.into())),
283 }
284 }
285}
286
287impl From<ES256OrES384> for Algorithm {
288 fn from(value: ES256OrES384) -> Self {
289 match value {
290 ES256OrES384::ES256 => Self::ES256,
291 ES256OrES384::ES384 => Self::ES384,
292 }
293 }
294}
295
296#[cfg(test)]
297mod tests {
298 use super::Algorithm;
299
300 #[test]
301 fn none_serializes() {
302 assert_eq!(
303 serde_json::to_string(&Algorithm::None).unwrap(),
304 r#""none""#
305 )
306 }
307
308 #[test]
309 fn none_deserializes() {
310 assert_eq!(
311 serde_json::from_str::<Algorithm>(r#""none""#).unwrap(),
312 Algorithm::None
313 );
314 assert_eq!(
315 serde_json::from_str::<Algorithm>(r#""None""#).unwrap(),
316 Algorithm::None
317 )
318 }
319}