ssi_crypto/algorithm/
mod.rs

1use core::fmt;
2
3use serde::{Deserialize, Serialize};
4
5pub trait SignatureAlgorithmType {
6    type Instance: SignatureAlgorithmInstance<Algorithm = Self>;
7}
8
9pub trait SignatureAlgorithmInstance {
10    type Algorithm;
11
12    fn algorithm(&self) -> Self::Algorithm;
13}
14
15macro_rules! algorithms {
16    ($(
17        $(#[doc = $doc:tt])*
18        $(#[doc($doc_tag:ident)])?
19        $(#[serde $serde:tt])?
20        $id:ident $( ($arg:ty) )? : $name:literal
21    ),*) => {
22        /// Signature algorithm.
23        #[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Hash, Eq)]
24        pub enum Algorithm {
25            $(
26                $(#[doc = $doc])*
27                $(#[doc($doc_tag)])?
28                $(#[serde $serde])?
29                #[serde(rename = $name)]
30                $id,
31            )*
32            /// No signature.
33            ///
34            /// Per the specs it should only be `none` but `None` is kept for backwards
35            /// compatibility.
36            #[serde(alias = "None")]
37            None
38        }
39
40        impl Algorithm {
41            pub fn as_str(&self) -> &'static str {
42                match self {
43                    $(
44                        Self::$id => $name,
45                    )*
46                    Self::None => "none"
47                }
48            }
49
50            pub fn into_str(self) -> &'static str {
51                match self {
52                    $(
53                        Self::$id => $name,
54                    )*
55                    Self::None => "none"
56                }
57            }
58        }
59
60        impl SignatureAlgorithmType for Algorithm {
61            type Instance = AlgorithmInstance;
62        }
63
64        #[derive(Debug, Clone)]
65        pub enum AlgorithmInstance {
66            $(
67                $(#[doc = $doc])*
68                $(#[doc($doc_tag)])?
69                $(#[serde $serde])?
70                $id $( ($arg) )?,
71            )*
72            /// No signature
73            None
74        }
75
76        impl AlgorithmInstance {
77            pub fn algorithm(&self) -> Algorithm {
78                match self {
79                    $(Self::$id $( (algorithms!(@ignore_arg $arg)) )? => Algorithm::$id,)*
80                    Self::None => Algorithm::None
81                }
82            }
83        }
84
85        impl SignatureAlgorithmInstance for AlgorithmInstance {
86            type Algorithm = Algorithm;
87
88            fn algorithm(&self) -> Algorithm {
89                self.algorithm()
90            }
91        }
92
93        $(
94            $(#[doc = $doc])*
95            #[derive(Debug, Default, Clone, Copy, PartialEq, Hash, Eq)]
96            pub struct $id;
97
98            algorithms!(@instance $id $($arg)?);
99
100            impl TryFrom<Algorithm> for $id {
101                type Error = UnsupportedAlgorithm;
102
103                fn try_from(a: Algorithm) -> Result<Self, Self::Error> {
104                    match a {
105                        Algorithm::$id => Ok(Self),
106                        a => Err(UnsupportedAlgorithm(a))
107                    }
108                }
109            }
110
111            impl From<$id> for Algorithm {
112                fn from(_a: $id) -> Self {
113                    Self::$id
114                }
115            }
116        )*
117    };
118    { @instance $id:ident } => {
119        impl SignatureAlgorithmType for $id {
120            type Instance = Self;
121        }
122
123        impl SignatureAlgorithmInstance for $id {
124            type Algorithm = $id;
125
126            fn algorithm(&self) -> $id {
127                *self
128            }
129        }
130
131        impl TryFrom<AlgorithmInstance> for $id {
132            type Error = UnsupportedAlgorithm;
133
134            fn try_from(a: AlgorithmInstance) -> Result<Self, Self::Error> {
135                match a {
136                    AlgorithmInstance::$id => Ok(Self),
137                    other => Err(UnsupportedAlgorithm(other.algorithm()))
138                }
139            }
140        }
141
142        impl From<$id> for AlgorithmInstance {
143            fn from(_: $id) -> Self {
144                Self::$id
145            }
146        }
147    };
148    { @instance $id:ident $arg:ty } => {
149        impl SignatureAlgorithmType for $id {
150            type Instance = $arg;
151        }
152
153        impl SignatureAlgorithmInstance for $arg {
154            type Algorithm = $id;
155
156            fn algorithm(&self) -> $id {
157                $id
158            }
159        }
160
161        impl TryFrom<AlgorithmInstance> for $arg {
162            type Error = UnsupportedAlgorithm;
163
164            fn try_from(a: AlgorithmInstance) -> Result<Self, Self::Error> {
165                match a {
166                    AlgorithmInstance::$id(arg) => Ok(arg),
167                    other => Err(UnsupportedAlgorithm(other.algorithm()))
168                }
169            }
170        }
171
172        impl From<$arg> for AlgorithmInstance {
173            fn from(value: $arg) -> Self {
174                Self::$id(value)
175            }
176        }
177    };
178    { @ignore_arg $arg:ty } => { _ };
179}
180
181algorithms! {
182    /// HMAC using SHA-256.
183    ///
184    /// See: <https://www.rfc-editor.org/rfc/rfc7518.txt>
185    HS256: "HS256",
186
187    /// HMAC using SHA-384.
188    ///
189    /// See: <https://www.rfc-editor.org/rfc/rfc7518.txt>
190    HS384: "HS384",
191
192    /// HMAC using SHA-512.
193    ///
194    /// See: <https://www.rfc-editor.org/rfc/rfc7518.txt>
195    HS512: "HS512",
196
197    /// RSASSA-PKCS1-v1_5 using SHA-256.
198    ///
199    /// See: <https://www.rfc-editor.org/rfc/rfc7518.txt>
200    RS256: "RS256",
201
202    /// RSASSA-PKCS1-v1_5 using SHA-384.
203    ///
204    /// See: <https://www.rfc-editor.org/rfc/rfc7518.txt>
205    RS384: "RS384",
206
207    /// RSASSA-PKCS1-v1_5 using SHA-512.
208    ///
209    /// See: <https://www.rfc-editor.org/rfc/rfc7518.txt>
210    RS512: "RS512",
211
212    /// RSASSA-PSS using SHA-256 and MGF1 with SHA-256.
213    ///
214    /// See: <https://www.rfc-editor.org/rfc/rfc7518.txt>
215    PS256: "PS256",
216
217    /// RSASSA-PSS using SHA-384 and MGF1 with SHA-384.
218    ///
219    /// See: <https://www.rfc-editor.org/rfc/rfc7518.txt>
220    PS384: "PS384",
221
222    /// RSASSA-PSS using SHA-512 and MGF1 with SHA-512.
223    ///
224    /// See: <https://www.rfc-editor.org/rfc/rfc7518.txt>
225    PS512: "PS512",
226
227    /// Edwards-curve Digital Signature Algorithm (EdDSA) using SHA-256.
228    ///
229    /// The following curves are defined for use with `EdDSA`:
230    ///  - `Ed25519`
231    ///  - `Ed448`
232    ///
233    /// See: <https://www.rfc-editor.org/rfc/rfc8037>
234    EdDSA: "EdDSA",
235
236    /// EdDSA using SHA-256 and Blake2b as pre-hash function.
237    EdBlake2b: "EdBlake2b", // TODO Blake2b is supposed to replace SHA-256
238
239    /// ECDSA using P-256 and SHA-256.
240    ///
241    /// See: <https://www.rfc-editor.org/rfc/rfc7518.txt>
242    ES256: "ES256",
243
244    /// ECDSA using P-384 and SHA-384.
245    ///
246    /// See: <https://www.rfc-editor.org/rfc/rfc7518.txt>
247    ES384: "ES384",
248
249    /// ECDSA using secp256k1 (K-256) and SHA-256.
250    ///
251    /// See: <https://datatracker.ietf.org/doc/html/rfc8812>
252    ES256K: "ES256K",
253
254    /// ECDSA using secp256k1 (K-256) and SHA-256 with a recovery bit.
255    ///
256    /// `ES256K-R` is similar to `ES256K` with the recovery bit appended, making
257    /// the signature 65 bytes instead of 64. The recovery bit is used to
258    /// extract the public key from the signature.
259    ///
260    /// See: <https://github.com/decentralized-identity/EcdsaSecp256k1RecoverySignature2020#es256k-r>
261    ES256KR: "ES256K-R",
262
263    /// ECDSA using secp256k1 (K-256) and Keccak-256.
264    ///
265    /// Like `ES256K` but using Keccak-256 instead of SHA-256.
266    ESKeccakK: "ESKeccakK",
267
268    /// ECDSA using secp256k1 (K-256) and Keccak-256 with a recovery bit.
269    ///
270    /// Like `ES256K-R` but using Keccak-256 instead of SHA-256.
271    ESKeccakKR: "ESKeccakKR",
272
273    /// ECDSA using P-256 and Blake2b.
274    ESBlake2b: "ESBlake2b",
275
276    /// ECDSA using secp256k1 (K-256) and Blake2b.
277    ESBlake2bK: "ESBlake2bK",
278
279    /// BBS scheme.
280    Bbs(BbsInstance): "BBS",
281    // Bbs: "BBS",
282
283    #[doc(hidden)]
284    AleoTestnet1Signature: "AleoTestnet1Signature"
285}
286
287impl Algorithm {
288    /// Checks if this algorithm is compatible with the `other` algorithm.
289    ///
290    /// An algorithm `A` is compatible with `B` if `A` can be used to verify a
291    /// signature created from `B`.
292    pub fn is_compatible_with(&self, other: Self) -> bool {
293        match self {
294            Self::ES256K | Self::ES256KR | Self::ESKeccakK | Self::ESKeccakKR => matches!(
295                other,
296                Self::ES256K | Self::ES256KR | Self::ESKeccakK | Self::ESKeccakKR
297            ),
298            a => *a == other,
299        }
300    }
301}
302
303impl Default for Algorithm {
304    fn default() -> Self {
305        Self::None
306    }
307}
308
309impl AsRef<str> for Algorithm {
310    fn as_ref(&self) -> &str {
311        self.as_str()
312    }
313}
314
315impl fmt::Display for Algorithm {
316    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
317        self.as_str().fmt(f)
318    }
319}
320
321#[derive(Debug, thiserror::Error)]
322pub enum AlgorithmError {
323    /// Missing algorithm.
324    #[error("missing algorithm")]
325    Missing,
326
327    /// Unsupported algorithm.
328    #[error("unsupported signature algorithm `{0}`")]
329    Unsupported(Algorithm),
330}
331
332#[derive(Debug, thiserror::Error)]
333#[error("unsupported signature algorithm `{0}`")]
334pub struct UnsupportedAlgorithm(pub Algorithm);
335
336/// ECDSA using secp256k1 (K-256) and SHA-256, with or without recovery bit.
337#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
338pub enum AnyES256K {
339    /// ECDSA using secp256k1 (K-256) and SHA-256, without recovery bit.
340    ES256K,
341
342    /// ECDSA using secp256k1 (K-256) and SHA-256, with recovery bit.
343    ES256KR,
344}
345
346impl SignatureAlgorithmType for AnyES256K {
347    type Instance = Self;
348}
349
350impl SignatureAlgorithmInstance for AnyES256K {
351    type Algorithm = AnyES256K;
352
353    fn algorithm(&self) -> AnyES256K {
354        *self
355    }
356}
357
358impl TryFrom<Algorithm> for AnyES256K {
359    type Error = UnsupportedAlgorithm;
360
361    fn try_from(value: Algorithm) -> Result<Self, Self::Error> {
362        match value {
363            Algorithm::ES256K => Ok(Self::ES256K),
364            Algorithm::ES256KR => Ok(Self::ES256KR),
365            other => Err(UnsupportedAlgorithm(other)),
366        }
367    }
368}
369
370impl From<AnyES256K> for Algorithm {
371    fn from(value: AnyES256K) -> Self {
372        match value {
373            AnyES256K::ES256K => Self::ES256K,
374            AnyES256K::ES256KR => Self::ES256KR,
375        }
376    }
377}
378
379impl From<ES256K> for AnyES256K {
380    fn from(_value: ES256K) -> Self {
381        Self::ES256K
382    }
383}
384
385impl From<ES256KR> for AnyES256K {
386    fn from(_value: ES256KR) -> Self {
387        Self::ES256KR
388    }
389}
390
391/// ECDSA using secp256k1 (K-256) and SHA-256, with or without recovery bit.
392#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
393pub enum AnyESKeccakK {
394    /// ECDSA using secp256k1 (K-256) and Keccak-256.
395    ///
396    /// Like `ES256K` but using Keccak-256 instead of SHA-256.
397    ESKeccakK,
398
399    /// ECDSA using secp256k1 (K-256) and Keccak-256 with a recovery bit.
400    ///
401    /// Like `ES256K-R` but using Keccak-256 instead of SHA-256.
402    ESKeccakKR,
403}
404
405impl SignatureAlgorithmType for AnyESKeccakK {
406    type Instance = Self;
407}
408
409impl SignatureAlgorithmInstance for AnyESKeccakK {
410    type Algorithm = AnyESKeccakK;
411
412    fn algorithm(&self) -> AnyESKeccakK {
413        *self
414    }
415}
416
417impl TryFrom<Algorithm> for AnyESKeccakK {
418    type Error = UnsupportedAlgorithm;
419
420    fn try_from(value: Algorithm) -> Result<Self, Self::Error> {
421        match value {
422            Algorithm::ESKeccakK => Ok(Self::ESKeccakK),
423            Algorithm::ESKeccakKR => Ok(Self::ESKeccakKR),
424            other => Err(UnsupportedAlgorithm(other)),
425        }
426    }
427}
428
429impl From<AnyESKeccakK> for Algorithm {
430    fn from(value: AnyESKeccakK) -> Self {
431        match value {
432            AnyESKeccakK::ESKeccakK => Self::ESKeccakK,
433            AnyESKeccakK::ESKeccakKR => Self::ESKeccakKR,
434        }
435    }
436}
437
438impl From<AnyESKeccakK> for AlgorithmInstance {
439    fn from(value: AnyESKeccakK) -> Self {
440        match value {
441            AnyESKeccakK::ESKeccakK => Self::ESKeccakK,
442            AnyESKeccakK::ESKeccakKR => Self::ESKeccakKR,
443        }
444    }
445}
446
447impl From<ESKeccakK> for AnyESKeccakK {
448    fn from(_value: ESKeccakK) -> Self {
449        Self::ESKeccakK
450    }
451}
452
453impl From<ESKeccakKR> for AnyESKeccakK {
454    fn from(_value: ESKeccakKR) -> Self {
455        Self::ESKeccakKR
456    }
457}
458
459/// ECDSA using secp256k1 (K-256) and SHA-256, with or without recovery bit.
460#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
461pub enum AnyES {
462    /// ECDSA using secp256k1 (K-256) and SHA-256, without recovery bit.
463    ES256K,
464
465    /// ECDSA using secp256k1 (K-256) and SHA-256, with recovery bit.
466    ES256KR,
467
468    ESKeccakK,
469
470    /// ECDSA using secp256k1 (K-256) and Keccak-256 with a recovery bit.
471    ///
472    /// Like `ES256K-R` but using Keccak-256 instead of SHA-256.
473    ESKeccakKR,
474}
475
476impl SignatureAlgorithmType for AnyES {
477    type Instance = Self;
478}
479
480impl SignatureAlgorithmInstance for AnyES {
481    type Algorithm = AnyES;
482
483    fn algorithm(&self) -> AnyES {
484        *self
485    }
486}
487
488impl TryFrom<Algorithm> for AnyES {
489    type Error = UnsupportedAlgorithm;
490
491    fn try_from(value: Algorithm) -> Result<Self, Self::Error> {
492        match value {
493            Algorithm::ES256K => Ok(Self::ES256K),
494            Algorithm::ES256KR => Ok(Self::ES256KR),
495            other => Err(UnsupportedAlgorithm(other)),
496        }
497    }
498}
499
500impl From<AnyES> for Algorithm {
501    fn from(value: AnyES) -> Self {
502        match value {
503            AnyES::ES256K => Self::ES256K,
504            AnyES::ES256KR => Self::ES256KR,
505            AnyES::ESKeccakK => Self::ESKeccakK,
506            AnyES::ESKeccakKR => Self::ESKeccakKR,
507        }
508    }
509}
510
511impl From<ES256K> for AnyES {
512    fn from(_value: ES256K) -> Self {
513        Self::ES256K
514    }
515}
516
517impl From<ES256KR> for AnyES {
518    fn from(_value: ES256KR) -> Self {
519        Self::ES256KR
520    }
521}
522
523#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
524pub enum AnyBlake2b {
525    EdBlake2b,
526    ESBlake2bK,
527    ESBlake2b,
528}
529
530impl SignatureAlgorithmType for AnyBlake2b {
531    type Instance = Self;
532}
533
534impl SignatureAlgorithmInstance for AnyBlake2b {
535    type Algorithm = Self;
536
537    fn algorithm(&self) -> AnyBlake2b {
538        *self
539    }
540}
541
542impl From<AnyBlake2b> for Algorithm {
543    fn from(value: AnyBlake2b) -> Self {
544        match value {
545            AnyBlake2b::EdBlake2b => Self::EdBlake2b,
546            AnyBlake2b::ESBlake2bK => Self::ESBlake2bK,
547            AnyBlake2b::ESBlake2b => Self::ESBlake2b,
548        }
549    }
550}
551
552impl From<AnyBlake2b> for AlgorithmInstance {
553    fn from(value: AnyBlake2b) -> Self {
554        match value {
555            AnyBlake2b::EdBlake2b => Self::EdBlake2b,
556            AnyBlake2b::ESBlake2bK => Self::ESBlake2bK,
557            AnyBlake2b::ESBlake2b => Self::ESBlake2b,
558        }
559    }
560}
561
562impl TryFrom<Algorithm> for AnyBlake2b {
563    type Error = UnsupportedAlgorithm;
564
565    fn try_from(value: Algorithm) -> Result<Self, Self::Error> {
566        match value {
567            Algorithm::EdBlake2b => Ok(Self::EdBlake2b),
568            Algorithm::ESBlake2bK => Ok(Self::ESBlake2bK),
569            Algorithm::ESBlake2b => Ok(Self::ESBlake2b),
570            a => Err(UnsupportedAlgorithm(a)),
571        }
572    }
573}
574
575impl TryFrom<AlgorithmInstance> for AnyBlake2b {
576    type Error = UnsupportedAlgorithm;
577
578    fn try_from(value: AlgorithmInstance) -> Result<Self, Self::Error> {
579        match value {
580            AlgorithmInstance::EdBlake2b => Ok(Self::EdBlake2b),
581            AlgorithmInstance::ESBlake2bK => Ok(Self::ESBlake2bK),
582            AlgorithmInstance::ESBlake2b => Ok(Self::ESBlake2b),
583            a => Err(UnsupportedAlgorithm(a.algorithm())),
584        }
585    }
586}
587
588#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
589pub enum ES256OrES384 {
590    ES256,
591    ES384,
592}
593
594impl ES256OrES384 {
595    pub fn name(&self) -> &'static str {
596        match self {
597            Self::ES256 => "ES256",
598            Self::ES384 => "ES384",
599        }
600    }
601}
602
603impl SignatureAlgorithmType for ES256OrES384 {
604    type Instance = Self;
605}
606
607impl SignatureAlgorithmInstance for ES256OrES384 {
608    type Algorithm = Self;
609
610    fn algorithm(&self) -> Self {
611        *self
612    }
613}
614
615impl fmt::Display for ES256OrES384 {
616    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
617        self.name().fmt(f)
618    }
619}
620
621impl From<ES256OrES384> for Algorithm {
622    fn from(value: ES256OrES384) -> Self {
623        match value {
624            ES256OrES384::ES256 => Self::ES256,
625            ES256OrES384::ES384 => Self::ES384,
626        }
627    }
628}
629
630impl From<ES256OrES384> for AlgorithmInstance {
631    fn from(value: ES256OrES384) -> Self {
632        match value {
633            ES256OrES384::ES256 => Self::ES256,
634            ES256OrES384::ES384 => Self::ES384,
635        }
636    }
637}
638
639#[derive(Debug, Clone)]
640pub struct BbsInstance(pub Box<BbsParameters>);
641
642#[derive(Debug, Clone)]
643pub enum BbsParameters {
644    Baseline {
645        header: [u8; 64],
646    },
647    Blind {
648        header: [u8; 64],
649        commitment_with_proof: Option<Vec<u8>>,
650        signer_blind: Option<[u8; 32]>,
651    },
652}