crypto: Add a method to manually verify our own user identity
parent
d4fe6f5133
commit
4f46212d1a
|
@ -32,11 +32,15 @@ use ruma::{
|
|||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::to_value;
|
||||
use tracing::error;
|
||||
|
||||
use super::{atomic_bool_deserializer, atomic_bool_serializer};
|
||||
use crate::{
|
||||
error::SignatureError, olm::Utility, verification::VerificationMachine, CryptoStoreError,
|
||||
OutgoingVerificationRequest, ReadOnlyDevice, VerificationRequest,
|
||||
error::SignatureError,
|
||||
olm::Utility,
|
||||
store::{Changes, IdentityChanges},
|
||||
verification::VerificationMachine,
|
||||
CryptoStoreError, OutgoingVerificationRequest, ReadOnlyDevice, VerificationRequest,
|
||||
};
|
||||
|
||||
/// Enum over the different user identity types we can have.
|
||||
|
@ -103,6 +107,27 @@ impl Deref for OwnUserIdentity {
|
|||
}
|
||||
|
||||
impl OwnUserIdentity {
|
||||
/// Mark our user identity as verified.
|
||||
///
|
||||
/// This will mark the identity locally as verified and sign it with our own
|
||||
/// device.
|
||||
///
|
||||
/// Returns a signature upload request that needs to be sent out.
|
||||
pub async fn verify(&self) -> Result<SignatureUploadRequest, SignatureError> {
|
||||
self.mark_as_verified();
|
||||
|
||||
let changes = Changes {
|
||||
identities: IdentityChanges { changed: vec![self.inner.clone().into()], new: vec![] },
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
if let Err(e) = self.verification_machine.store.save_changes(changes).await {
|
||||
error!(error =? e, "Couldn't store our own user identity after marking it as verified");
|
||||
}
|
||||
|
||||
self.verification_machine.store.account.sign_master_key(self.master_key.clone()).await
|
||||
}
|
||||
|
||||
/// Send a verification request to our other devices.
|
||||
pub async fn request_verification(
|
||||
&self,
|
||||
|
@ -680,7 +705,7 @@ impl ReadOnlyUserIdentity {
|
|||
///
|
||||
/// Returns a `SignatureError` if the self signing key fails to be correctly
|
||||
/// verified by the given master key.
|
||||
pub fn new(
|
||||
pub(crate) fn new(
|
||||
master_key: MasterPubkey,
|
||||
self_signing_key: SelfSigningPubkey,
|
||||
) -> Result<Self, SignatureError> {
|
||||
|
@ -690,7 +715,7 @@ impl ReadOnlyUserIdentity {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub async fn from_private(identity: &crate::olm::PrivateCrossSigningIdentity) -> Self {
|
||||
pub(crate) async fn from_private(identity: &crate::olm::PrivateCrossSigningIdentity) -> Self {
|
||||
let master_key = identity.master_key.lock().await.as_ref().unwrap().public_key.clone();
|
||||
let self_signing_key =
|
||||
identity.self_signing_key.lock().await.as_ref().unwrap().public_key.clone();
|
||||
|
@ -747,7 +772,7 @@ impl ReadOnlyUserIdentity {
|
|||
///
|
||||
/// Returns an empty result if the signature check succeeded, otherwise a
|
||||
/// SignatureError indicating why the check failed.
|
||||
pub fn is_device_signed(&self, device: &ReadOnlyDevice) -> Result<(), SignatureError> {
|
||||
pub(crate) fn is_device_signed(&self, device: &ReadOnlyDevice) -> Result<(), SignatureError> {
|
||||
if self.user_id() != device.user_id() {
|
||||
return Err(SignatureError::UserIdMissmatch);
|
||||
}
|
||||
|
@ -790,7 +815,7 @@ impl ReadOnlyOwnUserIdentity {
|
|||
///
|
||||
/// Returns a `SignatureError` if the self signing key fails to be correctly
|
||||
/// verified by the given master key.
|
||||
pub fn new(
|
||||
pub(crate) fn new(
|
||||
master_key: MasterPubkey,
|
||||
self_signing_key: SelfSigningPubkey,
|
||||
user_signing_key: UserSigningPubkey,
|
||||
|
@ -836,7 +861,7 @@ impl ReadOnlyOwnUserIdentity {
|
|||
///
|
||||
/// Returns an empty result if the signature check succeeded, otherwise a
|
||||
/// SignatureError indicating why the check failed.
|
||||
pub fn is_identity_signed(
|
||||
pub(crate) fn is_identity_signed(
|
||||
&self,
|
||||
identity: &ReadOnlyUserIdentity,
|
||||
) -> Result<(), SignatureError> {
|
||||
|
@ -855,7 +880,7 @@ impl ReadOnlyOwnUserIdentity {
|
|||
///
|
||||
/// Returns an empty result if the signature check succeeded, otherwise a
|
||||
/// SignatureError indicating why the check failed.
|
||||
pub fn is_device_signed(&self, device: &ReadOnlyDevice) -> Result<(), SignatureError> {
|
||||
pub(crate) fn is_device_signed(&self, device: &ReadOnlyDevice) -> Result<(), SignatureError> {
|
||||
if self.user_id() != device.user_id() {
|
||||
return Err(SignatureError::UserIdMissmatch);
|
||||
}
|
||||
|
@ -886,7 +911,7 @@ impl ReadOnlyOwnUserIdentity {
|
|||
/// * `user_signing_key` - The new user signing key of user identity.
|
||||
///
|
||||
/// Returns a `SignatureError` if we failed to update the identity.
|
||||
pub fn update(
|
||||
pub(crate) fn update(
|
||||
&mut self,
|
||||
master_key: MasterPubkey,
|
||||
self_signing_key: SelfSigningPubkey,
|
||||
|
|
|
@ -54,7 +54,7 @@ pub(crate) use olm::ReadOnlyAccount;
|
|||
pub use olm::{CrossSigningStatus, EncryptionSettings};
|
||||
pub use requests::{
|
||||
IncomingResponse, KeysQueryRequest, OutgoingRequest, OutgoingRequests,
|
||||
OutgoingVerificationRequest, RoomMessageRequest, ToDeviceRequest,
|
||||
OutgoingVerificationRequest, RoomMessageRequest, ToDeviceRequest, UploadSigningKeysRequest,
|
||||
};
|
||||
pub use store::{CrossSigningKeyExport, CryptoStoreError, SecretImportError};
|
||||
pub use verification::{
|
||||
|
|
|
@ -32,7 +32,7 @@ use olm_rs::{
|
|||
};
|
||||
use ruma::{
|
||||
api::client::r0::keys::{upload_keys, upload_signatures::Request as SignatureUploadRequest},
|
||||
encryption::{DeviceKeys, OneTimeKey, SignedKey},
|
||||
encryption::{CrossSigningKey, DeviceKeys, OneTimeKey, SignedKey},
|
||||
events::{
|
||||
room::encrypted::{EncryptedEventScheme, EncryptedToDeviceEventContent},
|
||||
AnyToDeviceEvent, ToDeviceEvent,
|
||||
|
@ -52,11 +52,11 @@ use super::{
|
|||
};
|
||||
use crate::{
|
||||
error::{EventError, OlmResult, SessionCreationError},
|
||||
identities::ReadOnlyDevice,
|
||||
identities::{MasterPubkey, ReadOnlyDevice},
|
||||
requests::UploadSigningKeysRequest,
|
||||
store::{Changes, Store},
|
||||
utilities::encode,
|
||||
OlmError,
|
||||
OlmError, SignatureError,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -761,6 +761,42 @@ impl ReadOnlyAccount {
|
|||
PrivateCrossSigningIdentity::new_with_account(self).await
|
||||
}
|
||||
|
||||
pub(crate) async fn sign_cross_signing_key(
|
||||
&self,
|
||||
cross_signing_key: &mut CrossSigningKey,
|
||||
) -> Result<(), SignatureError> {
|
||||
let signature = self.sign_json(serde_json::to_value(&cross_signing_key)?).await;
|
||||
|
||||
cross_signing_key
|
||||
.signatures
|
||||
.entry(self.user_id().to_owned())
|
||||
.or_insert_with(BTreeMap::new)
|
||||
.insert(
|
||||
DeviceKeyId::from_parts(DeviceKeyAlgorithm::Ed25519, self.device_id()).to_string(),
|
||||
signature,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) async fn sign_master_key(
|
||||
&self,
|
||||
master_key: MasterPubkey,
|
||||
) -> Result<SignatureUploadRequest, SignatureError> {
|
||||
let public_key =
|
||||
master_key.get_first_key().ok_or(SignatureError::MissingSigningKey)?.to_string();
|
||||
let mut cross_signing_key = master_key.into();
|
||||
self.sign_cross_signing_key(&mut cross_signing_key).await?;
|
||||
|
||||
let mut signed_keys = BTreeMap::new();
|
||||
signed_keys
|
||||
.entry(self.user_id().to_owned())
|
||||
.or_insert_with(BTreeMap::new)
|
||||
.insert(public_key, serde_json::to_value(cross_signing_key)?);
|
||||
|
||||
Ok(SignatureUploadRequest::new(signed_keys))
|
||||
}
|
||||
|
||||
/// Convert a JSON value to the canonical representation and sign the JSON
|
||||
/// string.
|
||||
///
|
||||
|
|
|
@ -28,7 +28,7 @@ use ruma::{
|
|||
api::client::r0::keys::upload_signatures::Request as SignatureUploadRequest,
|
||||
encryption::{DeviceKeys, KeyUsage},
|
||||
events::secret::request::SecretName,
|
||||
DeviceKeyAlgorithm, DeviceKeyId, UserId,
|
||||
UserId,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Error as JsonError;
|
||||
|
@ -379,22 +379,11 @@ impl PrivateCrossSigningIdentity {
|
|||
|
||||
let mut public_key =
|
||||
master.cross_signing_key(account.user_id().to_owned(), KeyUsage::Master);
|
||||
let signature = account
|
||||
.sign_json(
|
||||
serde_json::to_value(&public_key)
|
||||
.expect("Can't convert own public master key to json"),
|
||||
)
|
||||
.await;
|
||||
|
||||
public_key
|
||||
.signatures
|
||||
.entry(account.user_id().to_owned())
|
||||
.or_insert_with(BTreeMap::new)
|
||||
.insert(
|
||||
DeviceKeyId::from_parts(DeviceKeyAlgorithm::Ed25519, account.device_id())
|
||||
.to_string(),
|
||||
signature,
|
||||
);
|
||||
account
|
||||
.sign_cross_signing_key(&mut public_key)
|
||||
.await
|
||||
.expect("Can't sign our freshly created master key with our account");
|
||||
|
||||
let master = MasterSigning { inner: master, public_key: public_key.into() };
|
||||
|
||||
|
|
Loading…
Reference in New Issue