Skip to main content

cesr/core/matter/code/
signature.rs

1use super::cesr_code::CesrCode;
2use super::matter_code::MatterCode;
3use super::sealed::Sealed;
4use crate::core::matter::error::ValidationError;
5#[cfg(feature = "alloc")]
6#[allow(
7    unused_imports,
8    reason = "alloc prelude items; subset used per cfg/feature combination"
9)]
10use alloc::string::ToString;
11
12/// CESR codes for supported digital signature algorithms.
13#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
14pub enum SignatureCode {
15    /// Ed25519 64-byte signature.
16    Ed25519Sig,
17    /// secp256k1 (ECDSA) 64-byte signature (r || s).
18    ECDSA256k1Sig,
19    /// secp256r1 / P-256 (ECDSA) 64-byte signature (r || s).
20    ECDSA256r1Sig,
21    /// Ed448 114-byte signature.
22    Ed448Sig,
23}
24
25impl Sealed for SignatureCode {}
26
27impl CesrCode for SignatureCode {
28    fn to_matter_code(&self) -> MatterCode {
29        match self {
30            Self::Ed25519Sig => MatterCode::Ed25519Sig,
31            Self::ECDSA256k1Sig => MatterCode::ECDSA256k1Sig,
32            Self::ECDSA256r1Sig => MatterCode::ECDSA256r1Sig,
33            Self::Ed448Sig => MatterCode::Ed448Sig,
34        }
35    }
36
37    fn as_str(&self) -> &'static str {
38        match self {
39            Self::Ed25519Sig => "0B",
40            Self::ECDSA256k1Sig => "0C",
41            Self::ECDSA256r1Sig => "0I",
42            Self::Ed448Sig => "1AAE",
43        }
44    }
45}
46
47impl TryFrom<MatterCode> for SignatureCode {
48    type Error = ValidationError;
49
50    fn try_from(code: MatterCode) -> Result<Self, Self::Error> {
51        match code {
52            MatterCode::Ed25519Sig => Ok(Self::Ed25519Sig),
53            MatterCode::ECDSA256k1Sig => Ok(Self::ECDSA256k1Sig),
54            MatterCode::ECDSA256r1Sig => Ok(Self::ECDSA256r1Sig),
55            MatterCode::Ed448Sig => Ok(Self::Ed448Sig),
56            _ => Err(ValidationError::UnknownMatterCode(code.to_string())),
57        }
58    }
59}
60
61impl From<SignatureCode> for MatterCode {
62    fn from(code: SignatureCode) -> Self {
63        code.to_matter_code()
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70    use crate::core::matter::code::MatterCode;
71
72    #[test]
73    fn signature_code_to_matter_code_roundtrip() {
74        let codes = [
75            (SignatureCode::Ed25519Sig, MatterCode::Ed25519Sig),
76            (SignatureCode::ECDSA256k1Sig, MatterCode::ECDSA256k1Sig),
77            (SignatureCode::ECDSA256r1Sig, MatterCode::ECDSA256r1Sig),
78            (SignatureCode::Ed448Sig, MatterCode::Ed448Sig),
79        ];
80        for (sc, mc) in codes {
81            assert_eq!(sc.to_matter_code(), mc);
82            assert_eq!(SignatureCode::try_from(mc).unwrap(), sc);
83            assert_eq!(MatterCode::from(sc), mc);
84        }
85    }
86
87    #[test]
88    fn signature_code_rejects_non_signature() {
89        assert!(SignatureCode::try_from(MatterCode::Ed25519).is_err());
90        assert!(SignatureCode::try_from(MatterCode::Blake3_256).is_err());
91        assert!(SignatureCode::try_from(MatterCode::Ed25519Seed).is_err());
92        assert!(SignatureCode::try_from(MatterCode::Short).is_err());
93    }
94
95    #[test]
96    fn signature_code_as_str() {
97        assert_eq!(SignatureCode::Ed25519Sig.as_str(), "0B");
98        assert_eq!(SignatureCode::ECDSA256k1Sig.as_str(), "0C");
99        assert_eq!(SignatureCode::ECDSA256r1Sig.as_str(), "0I");
100        assert_eq!(SignatureCode::Ed448Sig.as_str(), "1AAE");
101    }
102}