crypto: Add key export methods for inbound group sessions.
parent
98f69aed41
commit
aff1e1d0a8
|
@ -12,7 +12,12 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use std::{collections::BTreeMap, convert::TryInto, fmt, sync::Arc};
|
use std::{
|
||||||
|
collections::BTreeMap,
|
||||||
|
convert::{TryFrom, TryInto},
|
||||||
|
fmt,
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
use matrix_sdk_common::{
|
use matrix_sdk_common::{
|
||||||
events::{room::encrypted::EncryptedEventContent, AnySyncRoomEvent, SyncMessageEvent},
|
events::{room::encrypted::EncryptedEventContent, AnySyncRoomEvent, SyncMessageEvent},
|
||||||
|
@ -32,7 +37,7 @@ pub use olm_rs::{
|
||||||
utility::OlmUtility,
|
utility::OlmUtility,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::GroupSessionKey;
|
use super::{ExportedGroupSessionKey, ExportedRoomKey, GroupSessionKey};
|
||||||
use crate::error::{EventError, MegolmResult};
|
use crate::error::{EventError, MegolmResult};
|
||||||
|
|
||||||
/// Inbound group session.
|
/// Inbound group session.
|
||||||
|
@ -103,6 +108,39 @@ impl InboundGroupSession {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Export this session.
|
||||||
|
pub async fn export(&self) -> ExportedRoomKey {
|
||||||
|
self.export_at_index(self.first_known_index().await)
|
||||||
|
.await
|
||||||
|
.expect("Can't export at the first known index")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Export this session at the given message index.
|
||||||
|
pub async fn export_at_index(&self, message_index: u32) -> Option<ExportedRoomKey> {
|
||||||
|
let session_key =
|
||||||
|
ExportedGroupSessionKey(self.inner.lock().await.export(message_index).ok()?);
|
||||||
|
|
||||||
|
let mut sender_claimed_keys: BTreeMap<DeviceKeyAlgorithm, String> = BTreeMap::new();
|
||||||
|
|
||||||
|
sender_claimed_keys.insert(DeviceKeyAlgorithm::Ed25519, (&*self.signing_key).to_owned());
|
||||||
|
|
||||||
|
Some(ExportedRoomKey {
|
||||||
|
algorithm: EventEncryptionAlgorithm::MegolmV1AesSha2,
|
||||||
|
room_id: (&*self.room_id).clone(),
|
||||||
|
sender_key: (&*self.sender_key).to_owned(),
|
||||||
|
session_id: self.session_id().to_owned(),
|
||||||
|
forwarding_curve25519_key_chain: self
|
||||||
|
.forwarding_chains
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.as_ref()
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_default(),
|
||||||
|
sender_claimed_keys,
|
||||||
|
session_key,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Restore a Session from a previously pickled string.
|
/// Restore a Session from a previously pickled string.
|
||||||
///
|
///
|
||||||
/// Returns the restored group session or a `OlmGroupSessionError` if there
|
/// Returns the restored group session or a `OlmGroupSessionError` if there
|
||||||
|
|
|
@ -12,7 +12,12 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
use matrix_sdk_common::{
|
||||||
|
events::forwarded_room_key::ForwardedRoomKeyEventContent,
|
||||||
|
identifiers::{DeviceKeyAlgorithm, EventEncryptionAlgorithm, RoomId},
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::{collections::BTreeMap, convert::TryInto};
|
||||||
use zeroize::Zeroize;
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
mod inbound;
|
mod inbound;
|
||||||
|
@ -27,6 +32,86 @@ pub use outbound::{EncryptionSettings, OutboundGroupSession};
|
||||||
#[zeroize(drop)]
|
#[zeroize(drop)]
|
||||||
pub struct GroupSessionKey(pub String);
|
pub struct GroupSessionKey(pub String);
|
||||||
|
|
||||||
|
/// The exported version of an private session key of a group session.
|
||||||
|
/// Can be used to create a new inbound group session.
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize, Zeroize)]
|
||||||
|
#[zeroize(drop)]
|
||||||
|
pub struct ExportedGroupSessionKey(pub String);
|
||||||
|
|
||||||
|
/// An exported version of a `InboundGroupSession`
|
||||||
|
///
|
||||||
|
/// This can be used to share the `InboundGroupSession` in an exported file.
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct ExportedRoomKey {
|
||||||
|
/// The encryption algorithm that the session uses.
|
||||||
|
pub algorithm: EventEncryptionAlgorithm,
|
||||||
|
|
||||||
|
/// The room where the session is used.
|
||||||
|
pub room_id: RoomId,
|
||||||
|
|
||||||
|
/// The Curve25519 key of the device which initiated the session originally.
|
||||||
|
pub sender_key: String,
|
||||||
|
|
||||||
|
/// The ID of the session that the key is for.
|
||||||
|
pub session_id: String,
|
||||||
|
|
||||||
|
/// The key for the session.
|
||||||
|
pub session_key: ExportedGroupSessionKey,
|
||||||
|
|
||||||
|
/// The Ed25519 key of the device which initiated the session originally.
|
||||||
|
pub sender_claimed_keys: BTreeMap<DeviceKeyAlgorithm, String>,
|
||||||
|
|
||||||
|
/// Chain of Curve25519 keys through which this session was forwarded, via
|
||||||
|
/// m.forwarded_room_key events.
|
||||||
|
pub forwarding_curve25519_key_chain: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryInto<ForwardedRoomKeyEventContent> for ExportedRoomKey {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_into(self) -> Result<ForwardedRoomKeyEventContent, Self::Error> {
|
||||||
|
if self.sender_claimed_keys.len() != 1 {
|
||||||
|
Err(())
|
||||||
|
} else {
|
||||||
|
let (algorithm, claimed_key) = self.sender_claimed_keys.iter().next().ok_or(())?;
|
||||||
|
|
||||||
|
if algorithm != &DeviceKeyAlgorithm::Ed25519 {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ForwardedRoomKeyEventContent {
|
||||||
|
algorithm: self.algorithm,
|
||||||
|
room_id: self.room_id,
|
||||||
|
sender_key: self.sender_key,
|
||||||
|
session_id: self.session_id,
|
||||||
|
session_key: self.session_key.0.clone(),
|
||||||
|
sender_claimed_ed25519_key: claimed_key.to_owned(),
|
||||||
|
forwarding_curve25519_key_chain: self.forwarding_curve25519_key_chain,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ForwardedRoomKeyEventContent> for ExportedRoomKey {
|
||||||
|
fn from(forwarded_key: ForwardedRoomKeyEventContent) -> Self {
|
||||||
|
let mut sender_claimed_keys: BTreeMap<DeviceKeyAlgorithm, String> = BTreeMap::new();
|
||||||
|
sender_claimed_keys.insert(
|
||||||
|
DeviceKeyAlgorithm::Ed25519,
|
||||||
|
forwarded_key.sender_claimed_ed25519_key,
|
||||||
|
);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
algorithm: forwarded_key.algorithm,
|
||||||
|
room_id: forwarded_key.room_id,
|
||||||
|
session_id: forwarded_key.session_id,
|
||||||
|
forwarding_curve25519_key_chain: forwarded_key.forwarding_curve25519_key_chain,
|
||||||
|
sender_claimed_keys,
|
||||||
|
sender_key: forwarded_key.sender_key,
|
||||||
|
session_key: ExportedGroupSessionKey(forwarded_key.session_key),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::{
|
use std::{
|
||||||
|
|
|
@ -24,7 +24,8 @@ mod utility;
|
||||||
|
|
||||||
pub use account::{Account, AccountPickle, IdentityKeys, PickledAccount};
|
pub use account::{Account, AccountPickle, IdentityKeys, PickledAccount};
|
||||||
pub use group_sessions::{
|
pub use group_sessions::{
|
||||||
EncryptionSettings, InboundGroupSession, InboundGroupSessionPickle, PickledInboundGroupSession,
|
EncryptionSettings, ExportedRoomKey, InboundGroupSession, InboundGroupSessionPickle,
|
||||||
|
PickledInboundGroupSession,
|
||||||
};
|
};
|
||||||
pub(crate) use group_sessions::{GroupSessionKey, OutboundGroupSession};
|
pub(crate) use group_sessions::{GroupSessionKey, OutboundGroupSession};
|
||||||
pub use olm_rs::PicklingMode;
|
pub use olm_rs::PicklingMode;
|
||||||
|
|
Loading…
Reference in New Issue