Skip to main content

matrix_sdk_crypto/olm/signing/
pk_signing.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
15use 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/// Error type reporting failures in the signing operations.
36#[derive(Debug, Error)]
37pub enum SigningError {
38    /// Error decoding the base64 encoded pickle data.
39    #[error(transparent)]
40    Decode(#[from] DecodeError),
41
42    /// Error decrypting the pickled signing seed
43    #[error("Error decrypting the pickled signing seed")]
44    Decryption(String),
45
46    /// Error deserializing the pickle data.
47    #[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}