crypto: Add key export methods for inbound group sessions.
This commit is contained in:
parent
98f69aed41
commit
aff1e1d0a8
3 changed files with 127 additions and 3 deletions
|
@ -12,7 +12,12 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// 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::{
|
||||
events::{room::encrypted::EncryptedEventContent, AnySyncRoomEvent, SyncMessageEvent},
|
||||
|
@ -32,7 +37,7 @@ pub use olm_rs::{
|
|||
utility::OlmUtility,
|
||||
};
|
||||
|
||||
use super::GroupSessionKey;
|
||||
use super::{ExportedGroupSessionKey, ExportedRoomKey, GroupSessionKey};
|
||||
use crate::error::{EventError, MegolmResult};
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// Returns the restored group session or a `OlmGroupSessionError` if there
|
||||
|
|
|
@ -12,7 +12,12 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use matrix_sdk_common::{
|
||||
events::forwarded_room_key::ForwardedRoomKeyEventContent,
|
||||
identifiers::{DeviceKeyAlgorithm, EventEncryptionAlgorithm, RoomId},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{collections::BTreeMap, convert::TryInto};
|
||||
use zeroize::Zeroize;
|
||||
|
||||
mod inbound;
|
||||
|
@ -27,6 +32,86 @@ pub use outbound::{EncryptionSettings, OutboundGroupSession};
|
|||
#[zeroize(drop)]
|
||||
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)]
|
||||
mod test {
|
||||
use std::{
|
||||
|
|
|
@ -24,7 +24,8 @@ mod utility;
|
|||
|
||||
pub use account::{Account, AccountPickle, IdentityKeys, PickledAccount};
|
||||
pub use group_sessions::{
|
||||
EncryptionSettings, InboundGroupSession, InboundGroupSessionPickle, PickledInboundGroupSession,
|
||||
EncryptionSettings, ExportedRoomKey, InboundGroupSession, InboundGroupSessionPickle,
|
||||
PickledInboundGroupSession,
|
||||
};
|
||||
pub(crate) use group_sessions::{GroupSessionKey, OutboundGroupSession};
|
||||
pub use olm_rs::PicklingMode;
|
||||
|
|
Loading…
Reference in a new issue