matrix_sdk_crypto/types/cross_signing/
master.rs1use std::collections::btree_map::Iter;
16
17use ruma::{encryption::KeyUsage, DeviceKeyId, OwnedDeviceKeyId, UserId};
18use serde::{Deserialize, Serialize};
19use vodozemac::Ed25519PublicKey;
20
21use super::{CrossSigningKey, CrossSigningSubKeys, SigningKey};
22use crate::{
23 olm::VerifyJson,
24 types::{Signatures, SigningKeys},
25 SignatureError,
26};
27
28#[derive(Debug, Clone, Serialize, Deserialize)]
33#[serde(try_from = "CrossSigningKey")]
34pub struct MasterPubkey(pub(super) CrossSigningKey);
35
36impl MasterPubkey {
37 pub fn user_id(&self) -> &UserId {
39 &self.0.user_id
40 }
41
42 pub fn keys(&self) -> &SigningKeys<OwnedDeviceKeyId> {
44 &self.0.keys
45 }
46
47 pub fn usage(&self) -> &[KeyUsage] {
49 &self.0.usage
50 }
51
52 pub fn signatures(&self) -> &Signatures {
54 &self.0.signatures
55 }
56
57 pub fn get_key(&self, key_id: &DeviceKeyId) -> Option<&SigningKey> {
63 self.0.keys.get(key_id)
64 }
65
66 pub fn get_first_key(&self) -> Option<Ed25519PublicKey> {
71 self.0.get_first_key_and_id().map(|(_, k)| k)
72 }
73
74 pub(crate) fn has_signed_raw(
84 &self,
85 signatures: &Signatures,
86 canonical_json: &str,
87 ) -> Result<(), SignatureError> {
88 if let Some((key_id, key)) = self.0.get_first_key_and_id() {
89 key.verify_canonicalized_json(&self.0.user_id, key_id, signatures, canonical_json)
90 } else {
91 Err(SignatureError::UnsupportedAlgorithm)
92 }
93 }
94
95 pub(crate) fn verify_subkey<'a>(
104 &self,
105 subkey: impl Into<CrossSigningSubKeys<'a>>,
106 ) -> Result<(), SignatureError> {
107 let subkey: CrossSigningSubKeys<'_> = subkey.into();
108
109 if self.0.user_id != subkey.user_id() {
110 return Err(SignatureError::UserIdMismatch);
111 }
112
113 if let Some((key_id, key)) = self.0.get_first_key_and_id() {
114 key.verify_json(&self.0.user_id, key_id, subkey.cross_signing_key())
115 } else {
116 Err(SignatureError::UnsupportedAlgorithm)
117 }
118 }
119}
120
121impl<'a> IntoIterator for &'a MasterPubkey {
122 type Item = (&'a OwnedDeviceKeyId, &'a SigningKey);
123 type IntoIter = Iter<'a, OwnedDeviceKeyId, SigningKey>;
124
125 fn into_iter(self) -> Self::IntoIter {
126 self.keys().iter()
127 }
128}
129
130impl AsRef<CrossSigningKey> for MasterPubkey {
131 fn as_ref(&self) -> &CrossSigningKey {
132 &self.0
133 }
134}
135
136impl AsMut<CrossSigningKey> for MasterPubkey {
137 fn as_mut(&mut self) -> &mut CrossSigningKey {
138 &mut self.0
139 }
140}
141
142impl TryFrom<CrossSigningKey> for MasterPubkey {
143 type Error = serde_json::Error;
144
145 fn try_from(key: CrossSigningKey) -> Result<Self, Self::Error> {
146 if key.usage.contains(&KeyUsage::Master) && key.usage.len() == 1 {
147 Ok(Self(key))
148 } else {
149 Err(serde::de::Error::custom(format!(
150 "Expected cross signing key usage {} was not found",
151 KeyUsage::Master
152 )))
153 }
154 }
155}