1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use std::{
collections::HashMap,
convert::TryFrom,
fmt::{Debug, Display, Error as FmtError, Formatter},
};
use ruma_events::Algorithm;
use ruma_identifiers::{DeviceId, UserId};
use serde::{
de::{self, Unexpected},
Deserialize, Deserializer, Serialize, Serializer,
};
pub mod claim_keys;
pub mod get_key_changes;
pub mod get_keys;
pub mod upload_keys;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum KeyAlgorithm {
#[serde(rename = "ed25519")]
Ed25519,
#[serde(rename = "curve25519")]
Curve25519,
#[serde(rename = "signed_curve25519")]
SignedCurve25519,
}
impl Display for KeyAlgorithm {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
let algorithm_str = match *self {
KeyAlgorithm::Ed25519 => "ed25519",
KeyAlgorithm::Curve25519 => "curve25519",
KeyAlgorithm::SignedCurve25519 => "signed_curve25519",
};
write!(f, "{}", algorithm_str)?;
Ok(())
}
}
impl TryFrom<&'_ str> for KeyAlgorithm {
type Error = &'static str;
fn try_from(s: &str) -> Result<Self, Self::Error> {
match s {
"ed25519" => Ok(KeyAlgorithm::Ed25519),
"curve25519" => Ok(KeyAlgorithm::Curve25519),
"signed_curve25519" => Ok(KeyAlgorithm::SignedCurve25519),
_ => Err("Unknown algorithm"),
}
}
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct AlgorithmAndDeviceId(pub KeyAlgorithm, pub DeviceId);
impl Serialize for AlgorithmAndDeviceId {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let s = format!("{}:{}", self.0, self.1);
serializer.serialize_str(&s)
}
}
impl<'de> Deserialize<'de> for AlgorithmAndDeviceId {
#[allow(clippy::comparison_chain)]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let value = String::deserialize(deserializer)?;
let parts = value.split(':').collect::<Vec<_>>();
const EXPECTED: &str = "a string composed of an algorithm and a device id separated by ':'";
if parts.len() < 2 {
return Err(de::Error::invalid_type(
Unexpected::Other("string without a ':' separator"),
&EXPECTED,
));
} else if parts.len() > 2 {
return Err(de::Error::invalid_type(
Unexpected::Other("string with more than one ':' separator"),
&EXPECTED,
));
}
let algorithm_result = KeyAlgorithm::try_from(parts[0]);
match algorithm_result {
Ok(algorithm) => Ok(AlgorithmAndDeviceId(algorithm, parts[1].to_string())),
Err(_) => Err(de::Error::invalid_value(
Unexpected::Str(parts[0]),
&"valid key algorithm",
)),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeviceKeys {
pub user_id: UserId,
pub device_id: DeviceId,
pub algorithms: Vec<Algorithm>,
pub keys: HashMap<AlgorithmAndDeviceId, String>,
pub signatures: HashMap<UserId, HashMap<AlgorithmAndDeviceId, String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub unsigned: Option<UnsignedDeviceInfo>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UnsignedDeviceInfo {
pub device_display_name: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SignedKey {
pub key: String,
pub signatures: HashMap<UserId, HashMap<AlgorithmAndDeviceId, String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OneTimeKey {
SignedKey(SignedKey),
Key(String),
}