matrix_sdk_crypto/types/signatures/
signature.rs1use as_variant::as_variant;
17use ruma::DeviceKeyAlgorithm;
18use vodozemac::Ed25519Signature;
19
20use crate::types::InvalidSignature;
21
22#[derive(Clone, Debug, PartialEq, Eq)]
33pub enum Signature {
34 Ed25519(Ed25519Signature),
36 Other(String),
39}
40
41impl Signature {
42 pub fn ed25519(&self) -> Option<Ed25519Signature> {
44 as_variant!(self, Self::Ed25519).copied()
45 }
46
47 pub fn from_base64(algorithm: DeviceKeyAlgorithm, s: String) -> Result<Self, InvalidSignature> {
50 match algorithm {
51 DeviceKeyAlgorithm::Ed25519 => Ed25519Signature::from_base64(&s)
52 .map(|s| s.into())
53 .map_err(|_| InvalidSignature { source: s }),
54 _ => Ok(Signature::Other(s)),
55 }
56 }
57
58 pub fn to_base64(&self) -> String {
60 match self {
61 Signature::Ed25519(s) => s.to_base64(),
62 Signature::Other(s) => s.to_owned(),
63 }
64 }
65}
66
67impl From<Ed25519Signature> for Signature {
68 fn from(signature: Ed25519Signature) -> Self {
69 Self::Ed25519(signature)
70 }
71}
72
73#[cfg(test)]
74mod test {
75 use super::*;
76
77 #[test]
78 fn roundtrip_ed25519_signature() {
79 const BASE64_SIG: &str = "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ";
80
81 let parsed = Signature::from_base64(DeviceKeyAlgorithm::Ed25519, BASE64_SIG.to_owned())
82 .expect("Failed to parse");
83
84 let ed25519 = parsed.ed25519().expect("Not parsed as Ed25519");
85 assert_eq!(ed25519.to_base64(), BASE64_SIG);
86
87 let encoded = parsed.to_base64();
88 assert_eq!(encoded, BASE64_SIG)
89 }
90
91 #[test]
92 fn parse_invalid_ed25519_signature() {
93 const BASE64_SIG: &str = "XXXX";
94
95 let parsed = Signature::from_base64(DeviceKeyAlgorithm::Ed25519, BASE64_SIG.to_owned())
96 .expect_err("Expected an invalid signature");
97 assert_eq!(parsed.source, BASE64_SIG);
98 }
99
100 #[test]
101 fn roundtrip_other_signature() {
102 const TEXT: &str = "abcd";
103
104 let parsed = Signature::from_base64(DeviceKeyAlgorithm::from("foo"), TEXT.to_owned())
105 .expect("Failed to parse");
106
107 let other = as_variant!(&parsed, Signature::Other).expect("Not parsed as Other");
108 assert_eq!(other, TEXT);
109
110 let encoded = parsed.to_base64();
111 assert_eq!(encoded, TEXT)
112 }
113}