matrix_sdk_crypto/olm/signing/
pk_signing.rs1use ruma::{
16 CanonicalJsonValue, DeviceKeyAlgorithm, DeviceKeyId, OwnedUserId,
17 canonical_json::to_canonical_value, encryption::KeyUsage,
18};
19use serde::{Deserialize, Serialize};
20use serde_json::Error as JsonError;
21use thiserror::Error;
22use vodozemac::{DecodeError, Ed25519PublicKey, Ed25519SecretKey, Ed25519Signature, KeyError};
23use zeroize::Zeroize;
24
25use crate::{
26 OtherUserIdentityData,
27 error::SignatureError,
28 olm::utility::SignJson,
29 types::{
30 CrossSigningKey, DeviceKeys, MasterPubkey, SelfSigningPubkey, Signatures, SigningKeys,
31 UserSigningPubkey,
32 },
33};
34
35#[derive(Debug, Error)]
37pub enum SigningError {
38 #[error(transparent)]
40 Decode(#[from] DecodeError),
41
42 #[error("Error decrypting the pickled signing seed")]
44 Decryption(String),
45
46 #[error(transparent)]
48 Json(#[from] JsonError),
49}
50
51#[derive(Serialize, Deserialize)]
52pub struct Signing {
53 inner: Ed25519SecretKey,
54 public_key: Ed25519PublicKey,
55}
56
57#[cfg(not(tarpaulin_include))]
58impl std::fmt::Debug for Signing {
59 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
60 f.debug_struct("Signing").field("public_key", &self.public_key.to_base64()).finish()
61 }
62}
63
64impl PartialEq for Signing {
65 fn eq(&self, other: &Signing) -> bool {
66 self.public_key == other.public_key
67 }
68}
69
70impl SignJson for Signing {
71 fn sign_json(&self, value: CanonicalJsonValue) -> Result<Ed25519Signature, SignatureError> {
72 self.inner.sign_json(value)
73 }
74}
75
76#[derive(PartialEq, Debug)]
77pub struct MasterSigning {
78 inner: Signing,
79 public_key: MasterPubkey,
80}
81
82#[derive(Deserialize, Serialize)]
83#[allow(missing_debug_implementations)]
84pub struct PickledMasterSigning {
85 pickle: PickledSigning,
86 public_key: MasterPubkey,
87}
88
89#[derive(Deserialize, Serialize)]
90#[allow(missing_debug_implementations)]
91pub struct PickledUserSigning {
92 pickle: PickledSigning,
93 public_key: UserSigningPubkey,
94}
95
96#[derive(Deserialize, Serialize)]
97#[allow(missing_debug_implementations)]
98pub struct PickledSelfSigning {
99 pickle: PickledSigning,
100 public_key: SelfSigningPubkey,
101}
102
103impl MasterSigning {
104 pub fn new(user_id: OwnedUserId) -> Self {
105 let inner = Signing::new();
106 let public_key = inner
107 .cross_signing_key(user_id, KeyUsage::Master)
108 .try_into()
109 .expect("A freshly created master key can be converted into a MasterPubkey");
110 let mut key = Self { inner, public_key };
111 let mut cross_signing_key = key.public_key.as_ref().to_owned();
112
113 key.sign_subkey(&mut cross_signing_key);
114 key.public_key = cross_signing_key
115 .try_into()
116 .expect("A freshly signed master key can be converted into a MasterPubkey");
117
118 key
119 }
120
121 pub(crate) fn new_subkeys(&self) -> (UserSigning, SelfSigning) {
122 let user = Signing::new();
123 let mut public_key =
124 user.cross_signing_key(self.public_key.user_id().to_owned(), KeyUsage::UserSigning);
125
126 self.sign_subkey(&mut public_key);
127
128 let user = UserSigning {
129 inner: user,
130 public_key: public_key
131 .try_into()
132 .expect("We can always create a new random UserSigningPubkey"),
133 };
134
135 let self_signing = Signing::new();
136 let mut public_key = self_signing
137 .cross_signing_key(self.public_key.user_id().to_owned(), KeyUsage::SelfSigning);
138 self.sign_subkey(&mut public_key);
139
140 let self_signing = SelfSigning {
141 inner: self_signing,
142 public_key: public_key
143 .try_into()
144 .expect("We can always create a new random SelfSigningPubkey"),
145 };
146
147 (user, self_signing)
148 }
149
150 pub fn public_key(&self) -> &MasterPubkey {
151 &self.public_key
152 }
153
154 pub(crate) fn public_key_mut(&mut self) -> &mut MasterPubkey {
155 &mut self.public_key
156 }
157
158 pub fn pickle(&self) -> PickledMasterSigning {
159 let pickle = self.inner.pickle();
160 let public_key = self.public_key.clone();
161 PickledMasterSigning { pickle, public_key }
162 }
163
164 pub fn export_seed(&self) -> String {
165 self.inner.to_base64()
166 }
167
168 pub fn from_base64(user_id: OwnedUserId, key: &str) -> Result<Self, KeyError> {
169 let inner = Signing::from_base64(key)?;
170 let public_key = inner
171 .cross_signing_key(user_id, KeyUsage::Master)
172 .try_into()
173 .expect("A master key can always be imported from a base64 encoded value");
174
175 Ok(Self { inner, public_key })
176 }
177
178 pub fn from_pickle(pickle: PickledMasterSigning) -> Result<Self, SigningError> {
179 let inner = Signing::from_pickle(pickle.pickle)?;
180 let public_key = pickle.public_key;
181
182 Ok(Self { inner, public_key })
183 }
184
185 pub fn sign(&self, message: &str) -> Ed25519Signature {
186 self.inner.sign(message)
187 }
188
189 pub fn sign_subkey(&self, subkey: &mut CrossSigningKey) {
190 let json_subkey = to_canonical_value(&subkey).expect("Can't serialize cross signing key");
191 let signature = self.inner.sign_json(json_subkey).expect("Can't sign cross signing keys");
192
193 subkey.signatures.add_signature(
194 self.public_key.user_id().to_owned(),
195 DeviceKeyId::from_parts(
196 DeviceKeyAlgorithm::Ed25519,
197 self.inner.public_key.to_base64().as_str().into(),
198 ),
199 signature,
200 );
201 }
202}
203
204impl UserSigning {
205 pub fn pickle(&self) -> PickledUserSigning {
206 let pickle = self.inner.pickle();
207 let public_key = self.public_key.clone();
208 PickledUserSigning { pickle, public_key }
209 }
210
211 pub fn public_key(&self) -> &UserSigningPubkey {
212 &self.public_key
213 }
214
215 pub fn export_seed(&self) -> String {
216 self.inner.to_base64()
217 }
218
219 pub fn from_base64(user_id: OwnedUserId, key: &str) -> Result<Self, KeyError> {
220 let inner = Signing::from_base64(key)?;
221 let public_key = inner
222 .cross_signing_key(user_id, KeyUsage::UserSigning)
223 .try_into()
224 .expect("A user-signing key can always be imported from a base64 encoded value");
225
226 Ok(Self { inner, public_key })
227 }
228
229 pub fn sign_user(
230 &self,
231 user: &OtherUserIdentityData,
232 ) -> Result<CrossSigningKey, SignatureError> {
233 let signatures = self.sign_user_helper(user)?;
234 let mut master_key = user.master_key().as_ref().clone();
235
236 master_key.signatures = signatures;
237
238 Ok(master_key)
239 }
240
241 pub fn sign_user_helper(
242 &self,
243 user: &OtherUserIdentityData,
244 ) -> Result<Signatures, SignatureError> {
245 let user_master: &CrossSigningKey = user.master_key().as_ref();
246 let signature = self.inner.sign_json(to_canonical_value(user_master)?)?;
247
248 let mut signatures = Signatures::new();
249
250 signatures.add_signature(
251 self.public_key.user_id().to_owned(),
252 DeviceKeyId::from_parts(
253 DeviceKeyAlgorithm::Ed25519,
254 self.inner.public_key.to_base64().as_str().into(),
255 ),
256 signature,
257 );
258
259 Ok(signatures)
260 }
261
262 pub fn from_pickle(pickle: PickledUserSigning) -> Result<Self, SigningError> {
263 let inner = Signing::from_pickle(pickle.pickle)?;
264
265 Ok(Self { inner, public_key: pickle.public_key })
266 }
267}
268
269impl SelfSigning {
270 pub(crate) fn pickle(&self) -> PickledSelfSigning {
271 let pickle = self.inner.pickle();
272 let public_key = self.public_key.clone();
273 PickledSelfSigning { pickle, public_key }
274 }
275
276 pub fn public_key(&self) -> &SelfSigningPubkey {
277 &self.public_key
278 }
279
280 pub fn export_seed(&self) -> String {
281 self.inner.to_base64()
282 }
283
284 pub fn from_base64(user_id: OwnedUserId, key: &str) -> Result<Self, KeyError> {
285 let inner = Signing::from_base64(key)?;
286 let public_key = inner
287 .cross_signing_key(user_id, KeyUsage::SelfSigning)
288 .try_into()
289 .expect("A self-signing key can always be imported from a base64 encoded value");
290
291 Ok(Self { inner, public_key })
292 }
293
294 pub(crate) fn sign_device(&self, device_keys: &mut DeviceKeys) -> Result<(), SignatureError> {
295 let serialized = to_canonical_value(&device_keys)?;
296 let signature = self.inner.sign_json(serialized)?;
297
298 device_keys.signatures.add_signature(
299 self.public_key.user_id().to_owned(),
300 DeviceKeyId::from_parts(
301 DeviceKeyAlgorithm::Ed25519,
302 self.inner.public_key.to_base64().as_str().into(),
303 ),
304 signature,
305 );
306
307 Ok(())
308 }
309
310 pub(crate) fn from_pickle(pickle: PickledSelfSigning) -> Result<Self, SigningError> {
311 let inner = Signing::from_pickle(pickle.pickle)?;
312
313 Ok(Self { inner, public_key: pickle.public_key })
314 }
315}
316
317#[derive(PartialEq, Debug)]
318pub struct SelfSigning {
319 inner: Signing,
320 public_key: SelfSigningPubkey,
321}
322
323#[derive(PartialEq, Debug)]
324pub struct UserSigning {
325 inner: Signing,
326 public_key: UserSigningPubkey,
327}
328
329#[derive(Serialize, Deserialize)]
330#[allow(missing_debug_implementations)]
331pub struct PickledSignings {
332 pub master_key: Option<PickledMasterSigning>,
333 pub user_signing_key: Option<PickledUserSigning>,
334 pub self_signing_key: Option<PickledSelfSigning>,
335}
336
337#[derive(Serialize, Deserialize)]
338pub struct PickledSigning(Ed25519SecretKey);
339
340impl Signing {
341 pub fn new() -> Self {
342 let secret_key = Ed25519SecretKey::new();
343 Self::new_helper(secret_key)
344 }
345
346 fn new_helper(secret_key: Ed25519SecretKey) -> Self {
347 let public_key = secret_key.public_key();
348
349 Signing { inner: secret_key, public_key }
350 }
351
352 pub fn from_base64(key: &str) -> Result<Self, KeyError> {
353 let key = Ed25519SecretKey::from_base64(key)?;
354 Ok(Self::new_helper(key))
355 }
356
357 pub fn from_pickle(pickle: PickledSigning) -> Result<Self, SigningError> {
358 Ok(Self::new_helper(pickle.0))
359 }
360
361 pub fn to_base64(&self) -> String {
362 self.inner.to_base64()
363 }
364
365 pub fn pickle(&self) -> PickledSigning {
366 let mut bytes = self.inner.to_bytes();
367 let ret = PickledSigning(Ed25519SecretKey::from_slice(&bytes));
368
369 bytes.zeroize();
370
371 ret
372 }
373
374 pub fn public_key(&self) -> Ed25519PublicKey {
375 self.public_key
376 }
377
378 pub fn cross_signing_key(&self, user_id: OwnedUserId, usage: KeyUsage) -> CrossSigningKey {
379 let keys = SigningKeys::from([(
380 DeviceKeyId::from_parts(
381 DeviceKeyAlgorithm::Ed25519,
382 self.public_key().to_base64().as_str().into(),
383 ),
384 self.inner.public_key().into(),
385 )]);
386
387 CrossSigningKey::new(user_id, vec![usage], keys, Default::default())
388 }
389
390 pub fn sign(&self, message: &str) -> Ed25519Signature {
391 self.inner.sign(message.as_bytes())
392 }
393}