Skip to main content

matrix_sdk_crypto/types/cross_signing/
self_signing.rs

1use std::collections::btree_map::Iter;
2
3use ruma::{OwnedDeviceKeyId, UserId, encryption::KeyUsage};
4use serde::{Deserialize, Serialize};
5use vodozemac::Ed25519PublicKey;
6
7use super::{CrossSigningKey, SigningKey};
8use crate::{
9    DeviceData, SignatureError,
10    olm::VerifyJson,
11    types::{DeviceKeys, SigningKeys},
12};
13
14/// Wrapper for a cross signing key marking it as a self signing key.
15///
16/// Self signing keys are used to sign the user's own devices.
17#[derive(Debug, Clone, Serialize, Deserialize)]
18#[serde(try_from = "CrossSigningKey")]
19pub struct SelfSigningPubkey(pub(super) CrossSigningKey);
20
21impl SelfSigningPubkey {
22    /// Get the user id of the self signing key's owner.
23    pub fn user_id(&self) -> &UserId {
24        &self.0.user_id
25    }
26
27    /// Get the keys map of containing the self signing keys.
28    pub fn keys(&self) -> &SigningKeys<OwnedDeviceKeyId> {
29        &self.0.keys
30    }
31
32    /// Get the list of `KeyUsage` that is set for this key.
33    pub fn usage(&self) -> &[KeyUsage] {
34        &self.0.usage
35    }
36
37    /// Get the first available self signing key.
38    ///
39    /// There's usually only a single key so this will usually fetch the
40    /// only key.
41    pub fn get_first_key(&self) -> Option<Ed25519PublicKey> {
42        self.0.get_first_key_and_id().map(|(_, k)| k)
43    }
44
45    /// Verify that the [`DeviceKeys`] have a valid signature from this
46    /// self-signing key.
47    pub fn verify_device_keys(&self, device_keys: &DeviceKeys) -> Result<(), SignatureError> {
48        if let Some((key_id, key)) = self.0.get_first_key_and_id() {
49            key.verify_json(&self.0.user_id, key_id, device_keys)
50        } else {
51            Err(SignatureError::UnsupportedAlgorithm)
52        }
53    }
54
55    /// Check if the given device is signed by this self signing key.
56    ///
57    /// # Arguments
58    ///
59    /// * `device` - The device that should be checked for a valid signature.
60    ///
61    /// Returns an empty result if the signature check succeeded, otherwise a
62    /// SignatureError indicating why the check failed.
63    pub(crate) fn verify_device(&self, device: &DeviceData) -> Result<(), SignatureError> {
64        self.verify_device_keys(device.as_device_keys())
65    }
66}
67
68impl<'a> IntoIterator for &'a SelfSigningPubkey {
69    type Item = (&'a OwnedDeviceKeyId, &'a SigningKey);
70    type IntoIter = Iter<'a, OwnedDeviceKeyId, SigningKey>;
71
72    fn into_iter(self) -> Self::IntoIter {
73        self.keys().iter()
74    }
75}
76
77impl TryFrom<CrossSigningKey> for SelfSigningPubkey {
78    type Error = serde_json::Error;
79
80    fn try_from(key: CrossSigningKey) -> Result<Self, Self::Error> {
81        if key.usage.contains(&KeyUsage::SelfSigning) && key.usage.len() == 1 {
82            Ok(Self(key))
83        } else {
84            Err(serde::de::Error::custom(format!(
85                "Expected cross signing key usage {} was not found",
86                KeyUsage::SelfSigning
87            )))
88        }
89    }
90}
91
92impl AsRef<CrossSigningKey> for SelfSigningPubkey {
93    fn as_ref(&self) -> &CrossSigningKey {
94        &self.0
95    }
96}
97
98impl AsMut<CrossSigningKey> for SelfSigningPubkey {
99    fn as_mut(&mut self) -> &mut CrossSigningKey {
100        &mut self.0
101    }
102}