ruma-events: Add the majority of in-room verification events
This patch adds equivalent in-room versions of the m.key.verfication.* events we have for to-device events. The MSC that adds this is found over here: https://github.com/matrix-org/matrix-doc/pull/2241
This commit is contained in:
parent
7ec2b0b555
commit
4afafa8b37
@ -37,6 +37,16 @@ event_enum! {
|
||||
"m.call.hangup",
|
||||
"m.call.candidates",
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
"m.key.verification.start",
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
"m.key.verification.cancel",
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
"m.key.verification.accept",
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
"m.key.verification.key",
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
"m.key.verification.mac",
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
"m.reaction",
|
||||
"m.room.encrypted",
|
||||
"m.room.message",
|
||||
|
@ -1,9 +1,22 @@
|
||||
//! Modules for events in the *m.key.verification* namespace.
|
||||
//!
|
||||
//! This module also contains types shared by events in its child namespaces.
|
||||
//!
|
||||
//! The MSC for the in-room variants of the `m.key.verification.*` events can be found
|
||||
//! [here](https://github.com/matrix-org/matrix-doc/pull/2241).
|
||||
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use std::convert::TryFrom;
|
||||
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use ruma_identifiers::EventId;
|
||||
use ruma_serde::StringEnum;
|
||||
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use crate::room::relationships::{Reference, RelatesToJsonRepr, RelationJsonRepr};
|
||||
|
||||
pub mod accept;
|
||||
pub mod cancel;
|
||||
pub mod key;
|
||||
@ -64,6 +77,37 @@ pub enum ShortAuthenticationString {
|
||||
_Custom(String),
|
||||
}
|
||||
|
||||
/// The relation that contains info which event the reaction is applying to.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(try_from = "RelatesToJsonRepr", into = "RelatesToJsonRepr")]
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
pub struct Relation {
|
||||
/// The event that is being referenced.
|
||||
pub event_id: EventId,
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
impl From<Relation> for RelatesToJsonRepr {
|
||||
fn from(relation: Relation) -> Self {
|
||||
RelatesToJsonRepr::Relation(RelationJsonRepr::Reference(Reference {
|
||||
event_id: relation.event_id,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
impl TryFrom<RelatesToJsonRepr> for Relation {
|
||||
type Error = &'static str;
|
||||
|
||||
fn try_from(value: RelatesToJsonRepr) -> Result<Self, Self::Error> {
|
||||
if let RelatesToJsonRepr::Relation(RelationJsonRepr::Reference(r)) = value {
|
||||
Ok(Relation { event_id: r.event_id })
|
||||
} else {
|
||||
Err("Expected a relation with a rel_type of `reference`")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A Short Authentication String (SAS) verification method.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)]
|
||||
pub enum VerificationMethod {
|
||||
|
@ -3,6 +3,8 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use ruma_events_macros::BasicEventContent;
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use ruma_events_macros::MessageEventContent;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
@ -10,7 +12,17 @@ use super::{
|
||||
HashAlgorithm, KeyAgreementProtocol, MessageAuthenticationCode, ShortAuthenticationString,
|
||||
};
|
||||
|
||||
/// The payload for `AcceptEvent`.
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use super::Relation;
|
||||
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use crate::MessageEvent;
|
||||
|
||||
/// Accepts a previously sent *m.key.verification.start* message.
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
pub type AcceptEvent = MessageEvent<AcceptEventContent>;
|
||||
|
||||
/// The payload for a to-device `AcceptEvent`.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, BasicEventContent)]
|
||||
#[ruma_event(type = "m.key.verification.accept")]
|
||||
pub struct AcceptToDeviceEventContent {
|
||||
@ -25,6 +37,20 @@ pub struct AcceptToDeviceEventContent {
|
||||
pub method: AcceptMethod,
|
||||
}
|
||||
|
||||
/// The payload for a in-room `AcceptEvent`.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, MessageEventContent)]
|
||||
#[ruma_event(type = "m.key.verification.accept")]
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
pub struct AcceptEventContent {
|
||||
/// The method specific content.
|
||||
#[serde(flatten)]
|
||||
pub method: AcceptMethod,
|
||||
|
||||
/// Information about the related event.
|
||||
#[serde(rename = "m.relates_to")]
|
||||
pub relation: Relation,
|
||||
}
|
||||
|
||||
/// An enum representing the different method specific
|
||||
/// *m.key.verification.accept* content.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
@ -124,12 +150,16 @@ mod tests {
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use matches::assert_matches;
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use ruma_identifiers::event_id;
|
||||
use ruma_identifiers::user_id;
|
||||
use ruma_serde::Raw;
|
||||
use serde_json::{
|
||||
from_value as from_json_value, json, to_value as to_json_value, Value as JsonValue,
|
||||
};
|
||||
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use super::{AcceptEventContent, Relation};
|
||||
use super::{
|
||||
AcceptMethod, AcceptToDeviceEventContent, CustomContent, HashAlgorithm,
|
||||
KeyAgreementProtocol, MSasV1Content, MessageAuthenticationCode, ShortAuthenticationString,
|
||||
@ -198,6 +228,38 @@ mod tests {
|
||||
assert_eq!(to_json_value(&key_verification_accept).unwrap(), json_data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
fn in_room_serialization() {
|
||||
let event_id = event_id!("$1598361704261elfgc:localhost");
|
||||
|
||||
let key_verification_accept_content = AcceptEventContent {
|
||||
relation: Relation { event_id: event_id.clone() },
|
||||
method: AcceptMethod::MSasV1(MSasV1Content {
|
||||
hash: HashAlgorithm::Sha256,
|
||||
key_agreement_protocol: KeyAgreementProtocol::Curve25519,
|
||||
message_authentication_code: MessageAuthenticationCode::HkdfHmacSha256,
|
||||
short_authentication_string: vec![ShortAuthenticationString::Decimal],
|
||||
commitment: "test_commitment".into(),
|
||||
}),
|
||||
};
|
||||
|
||||
let json_data = json!({
|
||||
"method": "m.sas.v1",
|
||||
"commitment": "test_commitment",
|
||||
"key_agreement_protocol": "curve25519",
|
||||
"hash": "sha256",
|
||||
"message_authentication_code": "hkdf-hmac-sha256",
|
||||
"short_authentication_string": ["decimal"],
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.reference",
|
||||
"event_id": event_id,
|
||||
}
|
||||
});
|
||||
|
||||
assert_eq!(to_json_value(&key_verification_accept_content).unwrap(), json_data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialization() {
|
||||
let json = json!({
|
||||
@ -308,4 +370,48 @@ mod tests {
|
||||
&& fields.get("test").unwrap() == &JsonValue::from("field")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
fn in_room_deserialization() {
|
||||
let id = event_id!("$1598361704261elfgc:localhost");
|
||||
|
||||
let json = json!({
|
||||
"commitment": "test_commitment",
|
||||
"method": "m.sas.v1",
|
||||
"hash": "sha256",
|
||||
"key_agreement_protocol": "curve25519",
|
||||
"message_authentication_code": "hkdf-hmac-sha256",
|
||||
"short_authentication_string": ["decimal"],
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.reference",
|
||||
"event_id": id,
|
||||
}
|
||||
});
|
||||
|
||||
// Deserialize the content struct separately to verify `TryFromRaw` is implemented for it.
|
||||
assert_matches!(
|
||||
from_json_value::<Raw<AcceptEventContent>>(json)
|
||||
.unwrap()
|
||||
.deserialize()
|
||||
.unwrap(),
|
||||
AcceptEventContent {
|
||||
relation: Relation {
|
||||
event_id
|
||||
},
|
||||
method: AcceptMethod::MSasV1(MSasV1Content {
|
||||
commitment,
|
||||
hash,
|
||||
key_agreement_protocol,
|
||||
message_authentication_code,
|
||||
short_authentication_string,
|
||||
})
|
||||
} if commitment == "test_commitment"
|
||||
&& event_id == id
|
||||
&& hash == HashAlgorithm::Sha256
|
||||
&& key_agreement_protocol == KeyAgreementProtocol::Curve25519
|
||||
&& message_authentication_code == MessageAuthenticationCode::HkdfHmacSha256
|
||||
&& short_authentication_string == vec![ShortAuthenticationString::Decimal]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,22 @@
|
||||
//! Types for the *m.key.verification.cancel* event.
|
||||
|
||||
use ruma_events_macros::BasicEventContent;
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use ruma_events_macros::MessageEventContent;
|
||||
use ruma_serde::StringEnum;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// The payload for `CancelEvent`.
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use crate::MessageEvent;
|
||||
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use super::Relation;
|
||||
|
||||
/// Cancels a key verification process/request.
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
pub type CancelEvent = MessageEvent<CancelEventContent>;
|
||||
|
||||
/// The payload for a to-device `CancelEvent`.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, BasicEventContent)]
|
||||
#[ruma_event(type = "m.key.verification.cancel")]
|
||||
pub struct CancelToDeviceEventContent {
|
||||
@ -20,6 +32,24 @@ pub struct CancelToDeviceEventContent {
|
||||
pub code: CancelCode,
|
||||
}
|
||||
|
||||
/// The payload for an in-room `CancelEvent`.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, MessageEventContent)]
|
||||
#[ruma_event(type = "m.key.verification.cancel")]
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
pub struct CancelEventContent {
|
||||
/// A human readable description of the `code`.
|
||||
///
|
||||
/// The client should only rely on this string if it does not understand the `code`.
|
||||
pub reason: String,
|
||||
|
||||
/// The error code for why the process/request was cancelled by the user.
|
||||
pub code: CancelCode,
|
||||
|
||||
/// Information about the related event.
|
||||
#[serde(rename = "m.relates_to")]
|
||||
pub relation: Relation,
|
||||
}
|
||||
|
||||
/// An error code for why the process/request was cancelled by the user.
|
||||
///
|
||||
/// Custom error codes should use the Java package naming convention.
|
||||
|
@ -1,9 +1,21 @@
|
||||
//! Types for the *m.key.verification.key* event.
|
||||
|
||||
use ruma_events_macros::BasicEventContent;
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use ruma_events_macros::MessageEventContent;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// The payload for `KeyEvent`.
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use super::Relation;
|
||||
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use crate::MessageEvent;
|
||||
|
||||
/// Sends the ephemeral public key for a device to the partner device.
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
pub type KeyEvent = MessageEvent<KeyEventContent>;
|
||||
|
||||
/// The payload for a to-device `KeyEvent`.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, BasicEventContent)]
|
||||
#[ruma_event(type = "m.key.verification.key")]
|
||||
pub struct KeyToDeviceEventContent {
|
||||
@ -15,3 +27,16 @@ pub struct KeyToDeviceEventContent {
|
||||
/// The device's ephemeral public key, encoded as unpadded Base64.
|
||||
pub key: String,
|
||||
}
|
||||
|
||||
/// The payload for in-room `KeyEvent`.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, MessageEventContent)]
|
||||
#[ruma_event(type = "m.key.verification.key")]
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
pub struct KeyEventContent {
|
||||
/// The device's ephemeral public key, encoded as unpadded Base64.
|
||||
pub key: String,
|
||||
|
||||
/// Information about the related event.
|
||||
#[serde(rename = "m.relates_to")]
|
||||
pub relation: Relation,
|
||||
}
|
||||
|
@ -3,9 +3,21 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use ruma_events_macros::BasicEventContent;
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use ruma_events_macros::MessageEventContent;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// The payload for `MacEvent`.
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use super::Relation;
|
||||
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use crate::MessageEvent;
|
||||
|
||||
/// Sends the MAC of a device's key to the partner device.
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
pub type MacEvent = MessageEvent<MacEventContent>;
|
||||
|
||||
/// The payload for a to-device `MacEvent`.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, BasicEventContent)]
|
||||
#[ruma_event(type = "m.key.verification.mac")]
|
||||
pub struct MacToDeviceEventContent {
|
||||
@ -23,3 +35,22 @@ pub struct MacToDeviceEventContent {
|
||||
/// encoded as unpadded Base64.
|
||||
pub keys: String,
|
||||
}
|
||||
|
||||
/// The payload for an in-room `MacEvent`.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, MessageEventContent)]
|
||||
#[ruma_event(type = "m.key.verification.mac")]
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
pub struct MacEventContent {
|
||||
/// A map of the key ID to the MAC of the key, using the algorithm in the verification process.
|
||||
///
|
||||
/// The MAC is encoded as unpadded Base64.
|
||||
pub mac: BTreeMap<String, String>,
|
||||
|
||||
/// The MAC of the comma-separated, sorted, list of key IDs given in the `mac` property,
|
||||
/// encoded as unpadded Base64.
|
||||
pub keys: String,
|
||||
|
||||
/// Information about the related event.
|
||||
#[serde(rename = "m.relates_to")]
|
||||
pub relation: Relation,
|
||||
}
|
||||
|
@ -3,16 +3,27 @@
|
||||
use std::{collections::BTreeMap, convert::TryFrom};
|
||||
|
||||
use ruma_events_macros::BasicEventContent;
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use ruma_events_macros::MessageEventContent;
|
||||
use ruma_identifiers::DeviceIdBox;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use super::Relation;
|
||||
use super::{
|
||||
HashAlgorithm, KeyAgreementProtocol, MessageAuthenticationCode, ShortAuthenticationString,
|
||||
};
|
||||
use crate::InvalidInput;
|
||||
|
||||
/// The payload of an *m.key.verification.start* event.
|
||||
use crate::InvalidInput;
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use crate::MessageEvent;
|
||||
|
||||
/// Begins an SAS key verification process.
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
pub type StartEvent = MessageEvent<StartEventContent>;
|
||||
|
||||
/// The payload of a to-device *m.key.verification.start* event.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, BasicEventContent)]
|
||||
#[ruma_event(type = "m.key.verification.start")]
|
||||
pub struct StartToDeviceEventContent {
|
||||
@ -31,6 +42,23 @@ pub struct StartToDeviceEventContent {
|
||||
pub method: StartMethod,
|
||||
}
|
||||
|
||||
/// The payload of an in-room *m.key.verification.start* event.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, MessageEventContent)]
|
||||
#[ruma_event(type = "m.key.verification.start")]
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
pub struct StartEventContent {
|
||||
/// The device ID which is initiating the process.
|
||||
pub from_device: DeviceIdBox,
|
||||
|
||||
/// Method specific content.
|
||||
#[serde(flatten)]
|
||||
pub method: StartMethod,
|
||||
|
||||
/// Information about the related event.
|
||||
#[serde(rename = "m.relates_to")]
|
||||
pub relation: Relation,
|
||||
}
|
||||
|
||||
/// An enum representing the different method specific
|
||||
/// *m.key.verification.start* content.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
@ -174,6 +202,8 @@ mod tests {
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use matches::assert_matches;
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use ruma_identifiers::event_id;
|
||||
use ruma_identifiers::user_id;
|
||||
use ruma_serde::Raw;
|
||||
use serde_json::{
|
||||
@ -185,6 +215,8 @@ mod tests {
|
||||
MessageAuthenticationCode, ShortAuthenticationString, StartMethod,
|
||||
StartToDeviceEventContent,
|
||||
};
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
use super::{Relation, StartEventContent};
|
||||
use crate::ToDeviceEvent;
|
||||
|
||||
#[test]
|
||||
@ -310,6 +342,41 @@ mod tests {
|
||||
assert_eq!(to_json_value(&key_verification_start).unwrap(), json_data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
fn in_room_serialization() {
|
||||
let event_id = event_id!("$1598361704261elfgc:localhost");
|
||||
|
||||
let key_verification_start_content = StartEventContent {
|
||||
from_device: "123".into(),
|
||||
relation: Relation { event_id: event_id.clone() },
|
||||
method: StartMethod::MSasV1(
|
||||
MSasV1Content::new(MSasV1ContentInit {
|
||||
hashes: vec![HashAlgorithm::Sha256],
|
||||
key_agreement_protocols: vec![KeyAgreementProtocol::Curve25519],
|
||||
message_authentication_codes: vec![MessageAuthenticationCode::HkdfHmacSha256],
|
||||
short_authentication_string: vec![ShortAuthenticationString::Decimal],
|
||||
})
|
||||
.unwrap(),
|
||||
),
|
||||
};
|
||||
|
||||
let json_data = json!({
|
||||
"from_device": "123",
|
||||
"method": "m.sas.v1",
|
||||
"key_agreement_protocols": ["curve25519"],
|
||||
"hashes": ["sha256"],
|
||||
"message_authentication_codes": ["hkdf-hmac-sha256"],
|
||||
"short_authentication_string": ["decimal"],
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.reference",
|
||||
"event_id": event_id,
|
||||
}
|
||||
});
|
||||
|
||||
assert_eq!(to_json_value(&key_verification_start_content).unwrap(), json_data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialization() {
|
||||
let json = json!({
|
||||
@ -423,6 +490,50 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "unstable-pre-spec")]
|
||||
fn in_room_deserialization() {
|
||||
let id = event_id!("$1598361704261elfgc:localhost");
|
||||
|
||||
let json = json!({
|
||||
"from_device": "123",
|
||||
"method": "m.sas.v1",
|
||||
"hashes": ["sha256"],
|
||||
"key_agreement_protocols": ["curve25519"],
|
||||
"message_authentication_codes": ["hkdf-hmac-sha256"],
|
||||
"short_authentication_string": ["decimal"],
|
||||
"m.relates_to": {
|
||||
"rel_type": "m.reference",
|
||||
"event_id": id,
|
||||
}
|
||||
});
|
||||
|
||||
// Deserialize the content struct separately to verify `TryFromRaw` is implemented for it.
|
||||
assert_matches!(
|
||||
from_json_value::<Raw<StartEventContent>>(json)
|
||||
.unwrap()
|
||||
.deserialize()
|
||||
.unwrap(),
|
||||
StartEventContent {
|
||||
from_device,
|
||||
relation: Relation {
|
||||
event_id,
|
||||
},
|
||||
method: StartMethod::MSasV1(MSasV1Content {
|
||||
hashes,
|
||||
key_agreement_protocols,
|
||||
message_authentication_codes,
|
||||
short_authentication_string,
|
||||
})
|
||||
} if from_device == "123"
|
||||
&& event_id == id
|
||||
&& hashes == vec![HashAlgorithm::Sha256]
|
||||
&& key_agreement_protocols == vec![KeyAgreementProtocol::Curve25519]
|
||||
&& message_authentication_codes == vec![MessageAuthenticationCode::HkdfHmacSha256]
|
||||
&& short_authentication_string == vec![ShortAuthenticationString::Decimal]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialization_failure() {
|
||||
// Ensure that invalid JSON creates a `serde_json::Error` and not `InvalidEvent`
|
||||
|
Loading…
x
Reference in New Issue
Block a user