Skip to main content

matrix_sdk_crypto/olm/signing/
mod.rs

1// Copyright 2020 The Matrix.org Foundation C.I.C.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15mod pk_signing;
16
17use std::sync::{
18    Arc,
19    atomic::{AtomicBool, Ordering},
20};
21
22pub use pk_signing::{MasterSigning, PickledSignings, SelfSigning, SigningError, UserSigning};
23use ruma::{
24    DeviceKeyAlgorithm, DeviceKeyId, OwnedDeviceId, OwnedDeviceKeyId, OwnedUserId, UserId,
25    api::client::keys::upload_signatures::v3::{Request as SignatureUploadRequest, SignedKeys},
26    events::secret::request::SecretName,
27};
28use serde::{Deserialize, Serialize};
29use tokio::sync::Mutex;
30use vodozemac::Ed25519Signature;
31
32use super::StaticAccountData;
33#[cfg(feature = "experimental-x509-identity-verification")]
34use crate::x509::X509Signer;
35use crate::{
36    Account, DeviceData, OtherUserIdentityData, OwnUserIdentity, OwnUserIdentityData,
37    error::SignatureError,
38    store::SecretImportError,
39    types::{
40        CrossSigningKey, DeviceKeys, MasterPubkey, SelfSigningPubkey, UserSigningPubkey,
41        requests::UploadSigningKeysRequest,
42    },
43};
44
45/// Private cross signing identity.
46///
47/// This object holds the private and public ed25519 key triplet that is used
48/// for cross signing.
49///
50/// The object might be completely empty or have only some of the key pairs
51/// available.
52///
53/// It can be used to sign devices or other identities.
54#[derive(Clone, Debug)]
55pub struct PrivateCrossSigningIdentity {
56    user_id: OwnedUserId,
57    shared: Arc<AtomicBool>,
58    pub(crate) master_key: Arc<Mutex<Option<MasterSigning>>>,
59    pub(crate) user_signing_key: Arc<Mutex<Option<UserSigning>>>,
60    pub(crate) self_signing_key: Arc<Mutex<Option<SelfSigning>>>,
61}
62
63/// A struct containing information on whether any of our cross-signing keys
64/// differ from the public keys that exist on the server.
65#[derive(Debug, Clone)]
66pub struct DiffResult {
67    /// Does the master key differ?
68    master_differs: bool,
69    /// Does the self-signing key differ?
70    self_signing_differs: bool,
71    /// Does the user-signing key differ?
72    user_signing_differs: bool,
73}
74
75impl DiffResult {
76    /// Do any of the cross-signing keys differ?
77    pub fn any_differ(&self) -> bool {
78        self.master_differs || self.self_signing_differs || self.user_signing_differs
79    }
80
81    /// Do none of the cross-signing keys differ?
82    pub fn none_differ(&self) -> bool {
83        !self.master_differs && !self.self_signing_differs && !self.user_signing_differs
84    }
85}
86
87/// The pickled version of a `PrivateCrossSigningIdentity`.
88///
89/// Can be used to store the identity.
90#[derive(Serialize, Deserialize)]
91#[allow(missing_debug_implementations)]
92pub struct PickledCrossSigningIdentity {
93    /// The user id of the identity owner.
94    pub user_id: OwnedUserId,
95    /// Have the public keys of the identity been shared.
96    pub shared: bool,
97    /// The pickled signing keys
98    pub keys: PickledSignings,
99}
100
101/// Struct representing the state of our private cross signing keys, it shows
102/// which private cross signing keys we have locally stored.
103#[derive(Debug, Clone, Serialize, Deserialize)]
104pub struct CrossSigningStatus {
105    /// Do we have the master key.
106    pub has_master: bool,
107    /// Do we have the self signing key, this one is necessary to sign our own
108    /// devices.
109    pub has_self_signing: bool,
110    /// Do we have the user signing key, this one is necessary to sign other
111    /// users.
112    pub has_user_signing: bool,
113}
114
115impl CrossSigningStatus {
116    /// Do we have all the cross signing keys locally stored.
117    pub fn is_complete(&self) -> bool {
118        self.has_master && self.has_user_signing && self.has_self_signing
119    }
120}
121
122impl PrivateCrossSigningIdentity {
123    /// Get the user id that this identity belongs to.
124    pub fn user_id(&self) -> &UserId {
125        &self.user_id
126    }
127
128    /// Is the identity empty.
129    ///
130    /// An empty identity doesn't contain any private keys.
131    ///
132    /// It is usual for the identity not to contain the master key since the
133    /// master key is only needed to sign the subkeys.
134    ///
135    /// An empty identity indicates that either no identity was created for this
136    /// use or that another device created it and hasn't shared it yet with us.
137    pub async fn is_empty(&self) -> bool {
138        let has_master = self.master_key.lock().await.is_some();
139        let has_user = self.user_signing_key.lock().await.is_some();
140        let has_self = self.self_signing_key.lock().await.is_some();
141
142        !(has_master && has_user && has_self)
143    }
144
145    /// Get the key ID of the master key.
146    pub async fn master_key_id(&self) -> Option<OwnedDeviceKeyId> {
147        let master_key = self.master_public_key().await?.get_first_key()?.to_base64();
148        let master_key = OwnedDeviceId::from(master_key);
149
150        Some(DeviceKeyId::from_parts(DeviceKeyAlgorithm::Ed25519, &master_key))
151    }
152
153    /// Can we sign our own devices, i.e. do we have a self signing key.
154    pub async fn can_sign_devices(&self) -> bool {
155        self.self_signing_key.lock().await.is_some()
156    }
157
158    /// Can we sign other users, i.e. do we have a user signing key.
159    pub async fn can_sign_users(&self) -> bool {
160        self.user_signing_key.lock().await.is_some()
161    }
162
163    /// Do we have the master key.
164    pub async fn has_master_key(&self) -> bool {
165        self.master_key.lock().await.is_some()
166    }
167
168    /// Get the status of our private cross signing keys, i.e. if we have the
169    /// master key and the subkeys.
170    pub async fn status(&self) -> CrossSigningStatus {
171        CrossSigningStatus {
172            has_master: self.has_master_key().await,
173            has_self_signing: self.can_sign_devices().await,
174            has_user_signing: self.can_sign_users().await,
175        }
176    }
177
178    /// Get the public part of the master key, if we have one.
179    pub async fn master_public_key(&self) -> Option<MasterPubkey> {
180        self.master_key.lock().await.as_ref().map(|m| m.public_key().to_owned())
181    }
182
183    /// Get the public part of the self-signing key, if we have one.
184    pub async fn self_signing_public_key(&self) -> Option<SelfSigningPubkey> {
185        self.self_signing_key.lock().await.as_ref().map(|k| k.public_key().to_owned())
186    }
187
188    /// Get the public part of the user-signing key, if we have one.
189    pub async fn user_signing_public_key(&self) -> Option<UserSigningPubkey> {
190        self.user_signing_key.lock().await.as_ref().map(|k| k.public_key().to_owned())
191    }
192
193    /// Export the seed of the private cross signing key
194    ///
195    /// The exported seed will be encoded as unpadded base64.
196    ///
197    /// # Arguments
198    ///
199    /// * `secret_name` - The type of the cross signing key that should be
200    ///   exported.
201    pub async fn export_secret(&self, secret_name: &SecretName) -> Option<String> {
202        match secret_name {
203            SecretName::CrossSigningMasterKey => {
204                self.master_key.lock().await.as_ref().map(|m| m.export_seed())
205            }
206            SecretName::CrossSigningUserSigningKey => {
207                self.user_signing_key.lock().await.as_ref().map(|m| m.export_seed())
208            }
209            SecretName::CrossSigningSelfSigningKey => {
210                self.self_signing_key.lock().await.as_ref().map(|m| m.export_seed())
211            }
212            _ => None,
213        }
214    }
215
216    pub(crate) async fn import_secret(
217        &self,
218        public_identity: OwnUserIdentity,
219        secret_name: &SecretName,
220        seed: &str,
221    ) -> Result<(), SecretImportError> {
222        let (master, self_signing, user_signing) = match secret_name {
223            SecretName::CrossSigningMasterKey => (Some(seed), None, None),
224            SecretName::CrossSigningSelfSigningKey => (None, Some(seed), None),
225            SecretName::CrossSigningUserSigningKey => (None, None, Some(seed)),
226            _ => return Ok(()),
227        };
228
229        self.import_secrets(public_identity, master, self_signing, user_signing).await
230    }
231
232    pub(crate) async fn import_secrets(
233        &self,
234        public_identity: OwnUserIdentity,
235        master_key: Option<&str>,
236        self_signing_key: Option<&str>,
237        user_signing_key: Option<&str>,
238    ) -> Result<(), SecretImportError> {
239        let master = if let Some(master_key) = master_key {
240            let master =
241                MasterSigning::from_base64(self.user_id().to_owned(), master_key).map_err(|e| {
242                    SecretImportError::Key { name: SecretName::CrossSigningMasterKey, error: e }
243                })?;
244
245            if public_identity.master_key() == master.public_key() {
246                Some(master)
247            } else {
248                return Err(SecretImportError::MismatchedPublicKeys {
249                    name: SecretName::CrossSigningMasterKey,
250                });
251            }
252        } else {
253            None
254        };
255
256        let user_signing = if let Some(user_signing_key) = user_signing_key {
257            let subkey = UserSigning::from_base64(self.user_id().to_owned(), user_signing_key)
258                .map_err(|e| SecretImportError::Key {
259                    name: SecretName::CrossSigningUserSigningKey,
260                    error: e,
261                })?;
262
263            if public_identity.user_signing_key() == subkey.public_key() {
264                Ok(Some(subkey))
265            } else {
266                Err(SecretImportError::MismatchedPublicKeys {
267                    name: SecretName::CrossSigningUserSigningKey,
268                })
269            }
270        } else {
271            Ok(None)
272        }?;
273
274        let self_signing = if let Some(self_signing_key) = self_signing_key {
275            let subkey = SelfSigning::from_base64(self.user_id().to_owned(), self_signing_key)
276                .map_err(|e| SecretImportError::Key {
277                    name: SecretName::CrossSigningSelfSigningKey,
278                    error: e,
279                })?;
280
281            if public_identity.self_signing_key() == subkey.public_key() {
282                Ok(Some(subkey))
283            } else {
284                Err(SecretImportError::MismatchedPublicKeys {
285                    name: SecretName::CrossSigningSelfSigningKey,
286                })
287            }
288        } else {
289            Ok(None)
290        }?;
291
292        if let Some(master) = master {
293            *self.master_key.lock().await = Some(master);
294        }
295
296        if let Some(self_signing) = self_signing {
297            *self.self_signing_key.lock().await = Some(self_signing);
298        }
299
300        if let Some(user_signing) = user_signing {
301            *self.user_signing_key.lock().await = Some(user_signing);
302        }
303
304        Ok(())
305    }
306
307    /// Import the private parts of the cross signing keys into this identity.
308    ///
309    /// The private parts should be unexpanded Ed25519 keys encoded as a base64
310    /// string.
311    ///
312    /// *Note*: This method won't check if the public keys match the public
313    /// keys present on the server.
314    pub async fn import_secrets_unchecked(
315        &self,
316        master_key: Option<&str>,
317        self_signing_key: Option<&str>,
318        user_signing_key: Option<&str>,
319    ) -> Result<(), SecretImportError> {
320        if let Some(master_key) = master_key {
321            let master =
322                MasterSigning::from_base64(self.user_id().to_owned(), master_key).map_err(|e| {
323                    SecretImportError::Key { name: SecretName::CrossSigningMasterKey, error: e }
324                })?;
325            *self.master_key.lock().await = Some(master);
326        }
327
328        if let Some(user_signing_key) = user_signing_key {
329            let subkey = UserSigning::from_base64(self.user_id().to_owned(), user_signing_key)
330                .map_err(|e| SecretImportError::Key {
331                    name: SecretName::CrossSigningUserSigningKey,
332                    error: e,
333                })?;
334            *self.user_signing_key.lock().await = Some(subkey);
335        }
336
337        if let Some(self_signing_key) = self_signing_key {
338            let subkey = SelfSigning::from_base64(self.user_id().to_owned(), self_signing_key)
339                .map_err(|e| SecretImportError::Key {
340                    name: SecretName::CrossSigningSelfSigningKey,
341                    error: e,
342                })?;
343            *self.self_signing_key.lock().await = Some(subkey);
344        }
345
346        Ok(())
347    }
348
349    /// Remove our private cross signing key if the public keys differ from
350    /// what's found in the [`OwnUserIdentityData`].
351    pub(crate) async fn clear_if_differs(
352        &self,
353        public_identity: &OwnUserIdentityData,
354    ) -> DiffResult {
355        let result = self.get_public_identity_diff(public_identity).await;
356
357        if result.master_differs {
358            *self.master_key.lock().await = None;
359        }
360
361        if result.user_signing_differs {
362            *self.user_signing_key.lock().await = None;
363        }
364
365        if result.self_signing_differs {
366            *self.self_signing_key.lock().await = None;
367        }
368
369        result
370    }
371
372    pub(crate) async fn get_public_identity_diff(
373        &self,
374        public_identity: &OwnUserIdentityData,
375    ) -> DiffResult {
376        let master_differs = self
377            .master_public_key()
378            .await
379            .is_some_and(|master| &master != public_identity.master_key());
380
381        let user_signing_differs = self
382            .user_signing_public_key()
383            .await
384            .is_some_and(|subkey| &subkey != public_identity.user_signing_key());
385
386        let self_signing_differs = self
387            .self_signing_public_key()
388            .await
389            .is_some_and(|subkey| &subkey != public_identity.self_signing_key());
390
391        DiffResult { master_differs, user_signing_differs, self_signing_differs }
392    }
393
394    /// Get the names of the secrets we are missing.
395    pub(crate) async fn get_missing_secrets(&self) -> Vec<SecretName> {
396        let mut missing = Vec::new();
397
398        if !self.has_master_key().await {
399            missing.push(SecretName::CrossSigningMasterKey);
400        }
401
402        if !self.can_sign_devices().await {
403            missing.push(SecretName::CrossSigningSelfSigningKey);
404        }
405
406        if !self.can_sign_users().await {
407            missing.push(SecretName::CrossSigningUserSigningKey);
408        }
409
410        missing
411    }
412
413    /// Create a new empty identity.
414    pub fn empty(user_id: &UserId) -> Self {
415        Self {
416            user_id: user_id.into(),
417            shared: Arc::new(AtomicBool::new(false)),
418            master_key: Arc::new(Mutex::new(None)),
419            self_signing_key: Arc::new(Mutex::new(None)),
420            user_signing_key: Arc::new(Mutex::new(None)),
421        }
422    }
423
424    async fn public_keys(
425        &self,
426    ) -> Result<(MasterPubkey, SelfSigningPubkey, UserSigningPubkey), SignatureError> {
427        let master_private_key = self.master_key.lock().await;
428        let master_private_key =
429            master_private_key.as_ref().ok_or(SignatureError::MissingSigningKey)?;
430        let self_signing_private_key = self.self_signing_key.lock().await;
431        let self_signing_private_key =
432            self_signing_private_key.as_ref().ok_or(SignatureError::MissingSigningKey)?;
433        let user_signing_private_key = self.user_signing_key.lock().await;
434        let user_signing_private_key =
435            user_signing_private_key.as_ref().ok_or(SignatureError::MissingSigningKey)?;
436
437        let mut master = master_private_key.public_key().to_owned();
438        let mut self_signing = self_signing_private_key.public_key().to_owned();
439        let mut user_signing = user_signing_private_key.public_key().to_owned();
440
441        master_private_key.sign_subkey(master.as_mut());
442        master_private_key.sign_subkey(self_signing.as_mut());
443        master_private_key.sign_subkey(user_signing.as_mut());
444
445        Ok((master, self_signing, user_signing))
446    }
447
448    pub(crate) async fn to_public_identity(&self) -> Result<OwnUserIdentityData, SignatureError> {
449        let (master, self_signing, user_signing) = self.public_keys().await?;
450
451        let identity = OwnUserIdentityData::new(master, self_signing, user_signing)?;
452        identity.mark_as_verified();
453
454        Ok(identity)
455    }
456
457    /// Sign the given public user identity with this private identity.
458    pub(crate) async fn sign_user(
459        &self,
460        user_identity: &OtherUserIdentityData,
461    ) -> Result<SignatureUploadRequest, SignatureError> {
462        let master_key = self
463            .user_signing_key
464            .lock()
465            .await
466            .as_ref()
467            .ok_or(SignatureError::MissingSigningKey)?
468            .sign_user(user_identity)?;
469
470        let mut user_signed_keys = SignedKeys::new();
471        user_signed_keys.add_cross_signing_keys(
472            user_identity
473                .master_key()
474                .get_first_key()
475                .ok_or(SignatureError::MissingSigningKey)?
476                .to_base64()
477                .into(),
478            master_key.to_raw(),
479        );
480
481        let signed_keys = [(user_identity.user_id().to_owned(), user_signed_keys)].into();
482        Ok(SignatureUploadRequest::new(signed_keys))
483    }
484
485    /// Sign the given device keys with this identity.
486    pub(crate) async fn sign_device(
487        &self,
488        device: &DeviceData,
489    ) -> Result<SignatureUploadRequest, SignatureError> {
490        let mut device_keys = device.as_device_keys().to_owned();
491        device_keys.signatures.clear();
492        self.sign_device_keys(&mut device_keys).await
493    }
494
495    /// Sign an Olm account with this private identity.
496    pub(crate) async fn sign_account(
497        &self,
498        account: &StaticAccountData,
499    ) -> Result<SignatureUploadRequest, SignatureError> {
500        let mut device_keys = account.unsigned_device_keys();
501        self.sign_device_keys(&mut device_keys).await
502    }
503
504    pub(crate) async fn sign_device_keys(
505        &self,
506        device_keys: &mut DeviceKeys,
507    ) -> Result<SignatureUploadRequest, SignatureError> {
508        self.self_signing_key
509            .lock()
510            .await
511            .as_ref()
512            .ok_or(SignatureError::MissingSigningKey)?
513            .sign_device(device_keys)?;
514
515        let mut user_signed_keys = SignedKeys::new();
516        user_signed_keys.add_device_keys(device_keys.device_id.clone(), device_keys.to_raw());
517
518        let signed_keys = [(self.user_id.clone(), user_signed_keys)].into();
519        Ok(SignatureUploadRequest::new(signed_keys))
520    }
521
522    pub(crate) async fn sign(&self, message: &str) -> Result<Ed25519Signature, SignatureError> {
523        Ok(self
524            .master_key
525            .lock()
526            .await
527            .as_ref()
528            .ok_or(SignatureError::MissingSigningKey)?
529            .sign(message))
530    }
531
532    fn new_helper(user_id: &UserId, master: MasterSigning) -> Self {
533        let (user, self_signing) = master.new_subkeys();
534
535        Self {
536            user_id: user_id.into(),
537            shared: Arc::new(AtomicBool::new(false)),
538            master_key: Arc::new(Mutex::new(Some(master))),
539            self_signing_key: Arc::new(Mutex::new(Some(self_signing))),
540            user_signing_key: Arc::new(Mutex::new(Some(user))),
541        }
542    }
543
544    /// Create a new cross signing identity without signing the device that
545    /// created it.
546    #[cfg(any(test, feature = "testing"))]
547    #[allow(dead_code)]
548    pub fn new(user_id: OwnedUserId) -> Self {
549        let master = MasterSigning::new(user_id.to_owned());
550        Self::new_helper(&user_id, master)
551    }
552
553    /**
554     * Create a new private identity, suitable for the given [`Account`].
555     *
556     * The identity will be created with a fresh set of cross-signing keys.
557     * The master key will be signed by the `OlmAccount` (i.e. the device).
558     * The user-signing and self-signing keys will be signed by the
559     * master key.
560     *
561     * Note that after creating a new identity, the device will need to be
562     * signed by the self-signing key. This can be done via
563     * [`PrivateCrossSigningIdentity::sign_account`].
564     *
565     * # Arguments
566     *
567     * * `account` - The Olm account that is creating the new identity.
568     */
569    pub(crate) fn for_account(
570        account: &Account,
571        #[cfg(feature = "experimental-x509-identity-verification")] x509_signer: Option<
572            &X509Signer,
573        >,
574    ) -> Result<PrivateCrossSigningIdentity, SignatureError> {
575        let mut master = MasterSigning::new(account.user_id().into());
576
577        // This is duplicated with
578        // `matrix_sdk_crypto::identities::user::OwnUserIdentity::verify`,
579        // but there's no good way to prevent this (at least not one we can see).
580        let cross_signing_key: &mut CrossSigningKey = &mut *master.public_key_mut().as_mut();
581
582        account.sign_cross_signing_key(cross_signing_key)?;
583
584        #[cfg(feature = "experimental-x509-identity-verification")]
585        if let Some(x509_signer) = x509_signer {
586            x509_signer.sign_cross_signing_key(&account.user_id, cross_signing_key)?;
587        }
588
589        Ok(Self::new_helper(account.user_id(), master))
590    }
591
592    #[cfg(any(test, feature = "testing"))]
593    #[allow(dead_code)]
594    /// Testing helper to reset this CrossSigning with a fresh one using the
595    /// local identity
596    pub fn reset(&mut self) {
597        let new = Self::new(self.user_id().to_owned());
598        *self = new
599    }
600
601    /// Mark the identity as shared.
602    pub fn mark_as_shared(&self) {
603        self.shared.store(true, Ordering::SeqCst)
604    }
605
606    /// Has the identity been shared.
607    ///
608    /// A shared identity here means that the public keys of the identity have
609    /// been uploaded to the server.
610    pub fn shared(&self) -> bool {
611        self.shared.load(Ordering::SeqCst)
612    }
613
614    /// Store the cross signing identity as a pickle.
615    ///
616    /// # Arguments
617    ///
618    /// * `pickle_key` - The key that should be used to encrypt the signing
619    ///   object, must be 32 bytes long.
620    ///
621    /// # Panics
622    ///
623    /// This will panic if the provided pickle key isn't 32 bytes long.
624    pub async fn pickle(&self) -> PickledCrossSigningIdentity {
625        let master_key = self.master_key.lock().await.as_ref().map(|m| m.pickle());
626
627        let self_signing_key = self.self_signing_key.lock().await.as_ref().map(|m| m.pickle());
628
629        let user_signing_key = self.user_signing_key.lock().await.as_ref().map(|m| m.pickle());
630
631        let keys = PickledSignings { master_key, user_signing_key, self_signing_key };
632
633        PickledCrossSigningIdentity { user_id: self.user_id.clone(), shared: self.shared(), keys }
634    }
635
636    /// Restore the private cross signing identity from a pickle.
637    ///
638    /// # Panic
639    ///
640    /// Panics if the pickle_key isn't 32 bytes long.
641    pub fn from_pickle(pickle: PickledCrossSigningIdentity) -> Result<Self, SigningError> {
642        let keys = pickle.keys;
643
644        let master = keys.master_key.map(MasterSigning::from_pickle).transpose()?;
645        let self_signing = keys.self_signing_key.map(SelfSigning::from_pickle).transpose()?;
646        let user_signing = keys.user_signing_key.map(UserSigning::from_pickle).transpose()?;
647
648        Ok(Self {
649            user_id: pickle.user_id.clone(),
650            shared: Arc::new(AtomicBool::from(pickle.shared)),
651            master_key: Arc::new(Mutex::new(master)),
652            self_signing_key: Arc::new(Mutex::new(self_signing)),
653            user_signing_key: Arc::new(Mutex::new(user_signing)),
654        })
655    }
656
657    /// Get the upload request that is needed to share the public keys of this
658    /// identity.
659    pub(crate) async fn as_upload_request(&self) -> UploadSigningKeysRequest {
660        let master_key =
661            self.master_key.lock().await.as_ref().map(|k| k.public_key().as_ref().clone());
662
663        let user_signing_key =
664            self.user_signing_key.lock().await.as_ref().map(|k| k.public_key().as_ref().clone());
665
666        let self_signing_key =
667            self.self_signing_key.lock().await.as_ref().map(|k| k.public_key().as_ref().clone());
668
669        UploadSigningKeysRequest { master_key, self_signing_key, user_signing_key }
670    }
671}
672
673#[cfg(test)]
674mod tests {
675    use std::sync::Arc;
676
677    use matrix_sdk_test::async_test;
678    use ruma::{CanonicalJsonValue, DeviceKeyAlgorithm, DeviceKeyId, UserId, device_id, user_id};
679    use serde_json::json;
680
681    use super::{PrivateCrossSigningIdentity, pk_signing::Signing};
682    use crate::{
683        identities::{DeviceData, OtherUserIdentityData},
684        olm::{Account, SignedJsonObject, VerifyJson},
685        types::Signatures,
686    };
687
688    fn user_id() -> &'static UserId {
689        user_id!("@example:localhost")
690    }
691
692    #[test]
693    fn test_signature_verification() {
694        let signing = Signing::new();
695        let user_id = user_id();
696        let key_id = DeviceKeyId::from_parts(DeviceKeyAlgorithm::Ed25519, "DEVICEID".into());
697
698        let json = json!({
699            "hello": "world"
700        });
701
702        let canonicalized: CanonicalJsonValue = json.try_into().unwrap();
703        let canonicalized = canonicalized.to_string();
704
705        let signature = signing.sign(&canonicalized);
706        let mut signatures = Signatures::new();
707        signatures.add_signature(user_id.to_owned(), key_id.clone(), signature);
708
709        let public_key = signing.public_key();
710
711        public_key
712            .verify_canonicalized_json(user_id, &key_id, &signatures, &canonicalized)
713            .expect("The signature can be verified");
714    }
715
716    #[test]
717    fn test_pickling_signing() {
718        let signing = Signing::new();
719        let pickled = signing.pickle();
720
721        let unpickled = Signing::from_pickle(pickled).unwrap();
722
723        assert_eq!(signing.public_key(), unpickled.public_key());
724    }
725
726    #[async_test]
727    async fn test_private_identity_creation() {
728        let identity = PrivateCrossSigningIdentity::new(user_id().to_owned());
729
730        let master_key = identity.master_key.lock().await;
731        let master_key = master_key.as_ref().unwrap();
732
733        master_key
734            .public_key()
735            .verify_subkey(identity.self_signing_key.lock().await.as_ref().unwrap().public_key())
736            .unwrap();
737
738        master_key
739            .public_key()
740            .verify_subkey(identity.user_signing_key.lock().await.as_ref().unwrap().public_key())
741            .unwrap();
742    }
743
744    #[async_test]
745    async fn test_identity_pickling() {
746        let identity = PrivateCrossSigningIdentity::new(user_id().to_owned());
747
748        let pickled = identity.pickle().await;
749
750        let unpickled = PrivateCrossSigningIdentity::from_pickle(pickled).unwrap();
751
752        assert_eq!(identity.user_id, unpickled.user_id);
753        assert_eq!(&*identity.master_key.lock().await, &*unpickled.master_key.lock().await);
754        assert_eq!(
755            &*identity.user_signing_key.lock().await,
756            &*unpickled.user_signing_key.lock().await
757        );
758        assert_eq!(
759            &*identity.self_signing_key.lock().await,
760            &*unpickled.self_signing_key.lock().await
761        );
762    }
763
764    #[async_test]
765    async fn test_private_identity_signed_by_account() {
766        let account = Account::with_device_id(user_id(), device_id!("DEVICEID"));
767        let identity = PrivateCrossSigningIdentity::for_account(
768            &account,
769            #[cfg(feature = "experimental-x509-identity-verification")]
770            None,
771        )
772        .unwrap();
773        let master = identity.master_key.lock().await;
774        let master = master.as_ref().unwrap();
775
776        let public_key = master.public_key().as_ref();
777        let signatures = &public_key.signatures;
778        let canonical_json = public_key.to_canonical_json().unwrap();
779
780        account
781            .has_signed_raw(signatures, &canonical_json)
782            .expect("The account should have signed the master key");
783
784        master
785            .public_key()
786            .has_signed_raw(signatures, &canonical_json)
787            .expect("The master key should have self-signed");
788
789        assert!(!master.public_key().signatures().is_empty());
790    }
791
792    #[cfg(feature = "experimental-x509-identity-verification")]
793    #[async_test]
794    async fn test_private_identity_signed_by_x509() {
795        use crate::x509::tests::create_rust_signer_and_verifier;
796
797        let account = Account::with_device_id(user_id(), device_id!("DEVICEID"));
798        let (cert, signing_key) =
799            crate::x509::tests::cert_and_key_with_email_in_subject_distinguished_name(
800                "example@localhost",
801            );
802
803        let (x509_signer, x509_verifier) = create_rust_signer_and_verifier(cert, signing_key);
804
805        // When we pass in an X509Signer to for_account, ...
806        let identity =
807            PrivateCrossSigningIdentity::for_account(&account, Some(&x509_signer)).unwrap();
808        let master = identity.master_key.lock().await;
809        let master = master.as_ref().unwrap();
810
811        let public_key = master.public_key().as_ref();
812
813        // ... the resulting cross-signing identity should be signed with X.509
814        assert!(x509_verifier.verify_signed_object(user_id(), public_key));
815    }
816
817    #[async_test]
818    async fn test_sign_device() {
819        let account = Account::with_device_id(user_id(), device_id!("DEVICEID"));
820        let identity = PrivateCrossSigningIdentity::for_account(
821            &account,
822            #[cfg(feature = "experimental-x509-identity-verification")]
823            None,
824        )
825        .unwrap();
826
827        let mut device = DeviceData::from_account(&account);
828        let self_signing = identity.self_signing_key.lock().await;
829        let self_signing = self_signing.as_ref().unwrap();
830
831        let mut device_keys = device.as_device_keys().to_owned();
832        self_signing.sign_device(&mut device_keys).unwrap();
833        device.update_device(&device_keys).unwrap();
834
835        let public_key = &self_signing.public_key();
836        public_key.verify_device(&device).unwrap()
837    }
838
839    #[async_test]
840    async fn test_sign_user_identity() {
841        let account = Account::with_device_id(user_id(), device_id!("DEVICEID"));
842        let identity = PrivateCrossSigningIdentity::for_account(
843            &account,
844            #[cfg(feature = "experimental-x509-identity-verification")]
845            None,
846        )
847        .unwrap();
848
849        let bob_account =
850            Account::with_device_id(user_id!("@bob:localhost"), device_id!("DEVICEID"));
851        let bob_private = PrivateCrossSigningIdentity::for_account(
852            &bob_account,
853            #[cfg(feature = "experimental-x509-identity-verification")]
854            None,
855        )
856        .unwrap();
857        let mut bob_public = OtherUserIdentityData::from_private(&bob_private).await;
858
859        let user_signing = identity.user_signing_key.lock().await;
860        let user_signing = user_signing.as_ref().unwrap();
861
862        let master = user_signing.sign_user(&bob_public).unwrap();
863
864        assert_eq!(
865            master.signatures.signature_count(),
866            1,
867            "We're only uploading our own signature"
868        );
869
870        bob_public.master_key = Arc::new(master.try_into().unwrap());
871
872        user_signing.public_key().verify_master_key(bob_public.master_key()).unwrap();
873    }
874}