Add events from the end-to-end encryption module.
This commit is contained in:
parent
12212789b3
commit
a0a9799c81
24
src/dummy.rs
Normal file
24
src/dummy.rs
Normal file
@ -0,0 +1,24 @@
|
||||
//! Types for the *m.dummy* event.
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
event! {
|
||||
/// This event type is used to indicate new Olm sessions for end-to-end encryption.
|
||||
///
|
||||
/// Typically it is encrypted as an *m.room.encrypted* event, then sent as a to-device event.
|
||||
///
|
||||
/// The event does not have any content associated with it. The sending client is expected to
|
||||
/// send a key share request shortly after this message, causing the receiving client to process
|
||||
/// this *m.dummy* event as the most recent event and using the keyshare request to set up the
|
||||
/// session. The keyshare request and *m.dummy* combination should result in the original
|
||||
/// sending client receiving keys over the newly established session.
|
||||
pub struct DummyEvent(DummyEventContent) {}
|
||||
}
|
||||
|
||||
/// The payload of an *m.dummy* event.
|
||||
///
|
||||
/// The values in the hash map are not meaningful. They are used to generate an empty JSON
|
||||
/// object to support the structure used by the Matrix specification.
|
||||
pub type DummyEventContent = HashMap<(), ()>;
|
47
src/forwarded_room_key.rs
Normal file
47
src/forwarded_room_key.rs
Normal file
@ -0,0 +1,47 @@
|
||||
//! Types for the *m.forwarded_room_key* event.
|
||||
|
||||
use ruma_identifiers::RoomId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::Algorithm;
|
||||
|
||||
event! {
|
||||
/// This event type is used to forward keys for end-to-end encryption.
|
||||
///
|
||||
/// Typically it is encrypted as an *m.room.encrypted* event, then sent as a to-device event.
|
||||
pub struct ForwardedRoomKeyEvent(ForwardedRoomKeyEventContent) {}
|
||||
}
|
||||
|
||||
/// The payload of an *m.forwarded_room_key* event.
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct ForwardedRoomKeyEventContent {
|
||||
/// The encryption algorithm the key in this event is to be used with.
|
||||
pub algorithm: Algorithm,
|
||||
|
||||
/// The room where the key 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 to be exchanged.
|
||||
pub session_key: String,
|
||||
|
||||
/// The Ed25519 key of the device which initiated the session originally.
|
||||
///
|
||||
/// It is "claimed" because the receiving device has no way to tell that the original room_key
|
||||
/// actually came from a device which owns the private part of this key unless they have done
|
||||
/// device verification.
|
||||
pub sender_claimed_ed25519_key: String,
|
||||
|
||||
/// Chain of Curve25519 keys.
|
||||
///
|
||||
/// It starts out empty, but each time the key is forwarded to another device, the previous
|
||||
/// sender in the chain is added to the end of the list. For example, if the key is forwarded
|
||||
/// from A to B to C, this field is empty between A and B, and contains A's Curve25519 key
|
||||
/// between B and C.
|
||||
pub forwarding_curve25519_key_chain: Vec<String>,
|
||||
}
|
3
src/key.rs
Normal file
3
src/key.rs
Normal file
@ -0,0 +1,3 @@
|
||||
//! Modules for events in the *m.key* namespace.
|
||||
|
||||
pub mod verification;
|
117
src/key/verification.rs
Normal file
117
src/key/verification.rs
Normal file
@ -0,0 +1,117 @@
|
||||
//! Modules for events in the *m.key.verification* namespace.
|
||||
//!
|
||||
//! This module also contains types shared by events in its child namespaces.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub mod accept;
|
||||
pub mod cancel;
|
||||
pub mod key;
|
||||
pub mod mac;
|
||||
pub mod request;
|
||||
pub mod start;
|
||||
|
||||
/// A hash algorithm.
|
||||
#[derive(Clone, Copy, Debug, Serialize, PartialEq, Deserialize)]
|
||||
pub enum HashAlgorithm {
|
||||
/// The SHA256 hash algorithm.
|
||||
#[serde(rename = "sha256")]
|
||||
Sha256,
|
||||
|
||||
/// Additional variants may be added in the future and will not be considered breaking changes
|
||||
/// to `ruma-events`.
|
||||
#[doc(hidden)]
|
||||
#[serde(skip)]
|
||||
__Nonexhaustive,
|
||||
}
|
||||
|
||||
impl_enum! {
|
||||
HashAlgorithm {
|
||||
Sha256 => "sha256",
|
||||
}
|
||||
}
|
||||
|
||||
/// A key agreement protocol.
|
||||
#[derive(Clone, Copy, Debug, Serialize, PartialEq, Deserialize)]
|
||||
pub enum KeyAgreementProtocol {
|
||||
/// The [Curve25519](https://cr.yp.to/ecdh.html) key agreement protocol.
|
||||
#[serde(rename = "curve25519")]
|
||||
Curve25519,
|
||||
|
||||
/// Additional variants may be added in the future and will not be considered breaking changes
|
||||
/// to `ruma-events`.
|
||||
#[doc(hidden)]
|
||||
#[serde(skip)]
|
||||
__Nonexhaustive,
|
||||
}
|
||||
|
||||
impl_enum! {
|
||||
KeyAgreementProtocol {
|
||||
Curve25519 => "curve25519",
|
||||
}
|
||||
}
|
||||
|
||||
/// A message authentication code algorithm.
|
||||
#[derive(Clone, Copy, Debug, Serialize, PartialEq, Deserialize)]
|
||||
pub enum MessageAuthenticationCode {
|
||||
/// The HKDF-HMAC-SHA256 MAC.
|
||||
#[serde(rename = "hkdf-hmac-sha256")]
|
||||
HkdfHmacSha256,
|
||||
|
||||
/// Additional variants may be added in the future and will not be considered breaking changes
|
||||
/// to `ruma-events`.
|
||||
#[doc(hidden)]
|
||||
#[serde(skip)]
|
||||
__Nonexhaustive,
|
||||
}
|
||||
|
||||
impl_enum! {
|
||||
MessageAuthenticationCode {
|
||||
HkdfHmacSha256 => "hkdf-hmac-sha256",
|
||||
}
|
||||
}
|
||||
|
||||
/// A Short Authentication String method.
|
||||
#[derive(Clone, Copy, Debug, Serialize, PartialEq, Deserialize)]
|
||||
pub enum ShortAuthenticationString {
|
||||
/// The decimal method.
|
||||
#[serde(rename = "decimal")]
|
||||
Decimal,
|
||||
|
||||
/// The emoji method.
|
||||
#[serde(rename = "emoji")]
|
||||
Emoji,
|
||||
|
||||
/// Additional variants may be added in the future and will not be considered breaking changes
|
||||
/// to `ruma-events`.
|
||||
#[doc(hidden)]
|
||||
#[serde(skip)]
|
||||
__Nonexhaustive,
|
||||
}
|
||||
|
||||
impl_enum! {
|
||||
ShortAuthenticationString {
|
||||
Decimal => "decimal",
|
||||
Emoji => "emoji",
|
||||
}
|
||||
}
|
||||
|
||||
/// A Short Authentication String (SAS) verification method.
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub enum VerificationMethod {
|
||||
/// The *m.sas.v1* verification method.
|
||||
#[serde(rename = "m.sas.v1")]
|
||||
MSasV1,
|
||||
|
||||
/// Additional variants may be added in the future and will not be considered breaking changes
|
||||
/// to `ruma-events`.
|
||||
#[doc(hidden)]
|
||||
#[serde(skip)]
|
||||
__Nonexhaustive,
|
||||
}
|
||||
|
||||
impl_enum! {
|
||||
VerificationMethod {
|
||||
MSasV1 => "m.sas.v1",
|
||||
}
|
||||
}
|
51
src/key/verification/accept.rs
Normal file
51
src/key/verification/accept.rs
Normal file
@ -0,0 +1,51 @@
|
||||
//! Types for the *m.key.verification.accept* event.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{
|
||||
HashAlgorithm, KeyAgreementProtocol, MessageAuthenticationCode, ShortAuthenticationString,
|
||||
VerificationMethod,
|
||||
};
|
||||
|
||||
event! {
|
||||
/// Accepts a previously sent *m.key.verification.start* messge.
|
||||
///
|
||||
/// Typically sent as a to-device event.
|
||||
pub struct AcceptEvent(AcceptEventContent) {}
|
||||
}
|
||||
|
||||
/// The payload of an *m.key.verification.accept* event.
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct AcceptEventContent {
|
||||
/// An opaque identifier for the verification process.
|
||||
///
|
||||
/// Must be the same as the one used for the *m.key.verification.start* message.
|
||||
pub transaction_id: String,
|
||||
|
||||
/// The verification method to use.
|
||||
///
|
||||
/// Must be `m.sas.v1`.
|
||||
pub method: VerificationMethod,
|
||||
|
||||
/// The key agreement protocol the device is choosing to use, out of the options in the
|
||||
/// *m.key.verification.start* message.
|
||||
pub key_agreement_protocol: KeyAgreementProtocol,
|
||||
|
||||
/// The hash method the device is choosing to use, out of the options in the
|
||||
/// *m.key.verification.start* message.
|
||||
pub hash: HashAlgorithm,
|
||||
|
||||
/// The message authentication code the device is choosing to use, out of the options in the
|
||||
/// *m.key.verification.start* message.
|
||||
pub message_authentication_code: MessageAuthenticationCode,
|
||||
|
||||
/// The SAS methods both devices involved in the verification process understand.
|
||||
///
|
||||
/// Must be a subset of the options in the *m.key.verification.start* message.
|
||||
pub short_authentication_string: Vec<ShortAuthenticationString>,
|
||||
|
||||
/// The hash (encoded as unpadded base64) of the concatenation of the device's ephemeral public
|
||||
/// key (encoded as unpadded base64) and the canonical JSON representation of the
|
||||
/// *m.key.verification.start* message.
|
||||
pub commitment: String,
|
||||
}
|
189
src/key/verification/cancel.rs
Normal file
189
src/key/verification/cancel.rs
Normal file
@ -0,0 +1,189 @@
|
||||
//! Types for the *m.key.verification.cancel* event.
|
||||
|
||||
use std::fmt::{Display, Formatter, Result as FmtResult};
|
||||
|
||||
use serde::{
|
||||
de::{Error as SerdeError, Visitor},
|
||||
Deserialize, Deserializer, Serialize, Serializer,
|
||||
};
|
||||
|
||||
event! {
|
||||
/// Cancels a key verification process/request.
|
||||
///
|
||||
/// Typically sent as a to-device event.
|
||||
pub struct CancelEvent(CancelEventContent) {}
|
||||
}
|
||||
|
||||
/// The payload of an *m.key.verification.cancel* event.
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct CancelEventContent {
|
||||
/// The opaque identifier for the verification process/request.
|
||||
pub transaction_id: String,
|
||||
|
||||
/// 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,
|
||||
}
|
||||
|
||||
/// An error code for why the process/request was cancelled by the user.
|
||||
///
|
||||
/// Custom error codes should use the Java package naming convention.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum CancelCode {
|
||||
/// The user cancelled the verification.
|
||||
User,
|
||||
|
||||
/// The verification process timed out. Verification processes can define their own timeout
|
||||
/// parameters.
|
||||
Timeout,
|
||||
|
||||
/// The device does not know about the given transaction ID.
|
||||
UnknownTransaction,
|
||||
|
||||
/// The device does not know how to handle the requested method.
|
||||
///
|
||||
/// This should be sent for *m.key.verification.start* messages and messages defined by
|
||||
/// individual verification processes.
|
||||
UnknownMethod,
|
||||
|
||||
/// The device received an unexpected message.
|
||||
///
|
||||
/// Typically raised when one of the parties is handling the verification out of order.
|
||||
UnexpectedMessage,
|
||||
|
||||
/// The key was not verified.
|
||||
KeyMismatch,
|
||||
|
||||
/// The expected user did not match the user verified.
|
||||
UserMismatch,
|
||||
|
||||
/// The message received was invalid.
|
||||
InvalidMessage,
|
||||
|
||||
/// An *m.key.verification.request* was accepted by a different device.
|
||||
///
|
||||
/// The device receiving this error can ignore the verification request.
|
||||
Accepted,
|
||||
|
||||
/// Any code that is not part of the specification.
|
||||
Custom(String),
|
||||
|
||||
/// Additional variants may be added in the future and will not be considered breaking changes
|
||||
/// to `ruma-events`.
|
||||
#[doc(hidden)]
|
||||
__Nonexhaustive,
|
||||
}
|
||||
|
||||
impl Display for CancelCode {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
let cancel_code_str = match *self {
|
||||
CancelCode::User => "m.user",
|
||||
CancelCode::Timeout => "m.timeout",
|
||||
CancelCode::UnknownTransaction => "m.unknown_transaction",
|
||||
CancelCode::UnknownMethod => "m.unknown_method",
|
||||
CancelCode::UnexpectedMessage => "m.unexpected_message",
|
||||
CancelCode::KeyMismatch => "m.key_mismatch",
|
||||
CancelCode::UserMismatch => "m.user_mismatch",
|
||||
CancelCode::InvalidMessage => "m.invalid_message",
|
||||
CancelCode::Accepted => "m.accepted",
|
||||
CancelCode::Custom(ref cancel_code) => cancel_code,
|
||||
CancelCode::__Nonexhaustive => {
|
||||
panic!("__Nonexhaustive enum variant is not intended for use.")
|
||||
}
|
||||
};
|
||||
|
||||
write!(f, "{}", cancel_code_str)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for CancelCode {
|
||||
fn from(s: &'a str) -> CancelCode {
|
||||
match s {
|
||||
"m.user" => CancelCode::User,
|
||||
"m.timeout" => CancelCode::Timeout,
|
||||
"m.unknown_transaction" => CancelCode::UnknownTransaction,
|
||||
"m.unknown_method" => CancelCode::UnknownMethod,
|
||||
"m.unexpected_message" => CancelCode::UnexpectedMessage,
|
||||
"m.key_mismatch" => CancelCode::KeyMismatch,
|
||||
"m.user_mismatch" => CancelCode::UserMismatch,
|
||||
"m.invalid_message" => CancelCode::InvalidMessage,
|
||||
"m.accepted" => CancelCode::Accepted,
|
||||
cancel_code => CancelCode::Custom(cancel_code.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for CancelCode {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for CancelCode {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct CancelCodeVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for CancelCodeVisitor {
|
||||
type Value = CancelCode;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(formatter, "an `m.key.verification.cancel` code as a string")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: SerdeError,
|
||||
{
|
||||
Ok(CancelCode::from(v))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_str(CancelCodeVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json::{from_str, to_string};
|
||||
|
||||
use super::CancelCode;
|
||||
|
||||
#[test]
|
||||
fn cancel_codes_serialize_to_display_form() {
|
||||
assert_eq!(to_string(&CancelCode::User).unwrap(), r#""m.user""#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_cancel_codes_serialize_to_display_form() {
|
||||
assert_eq!(
|
||||
to_string(&CancelCode::Custom("io.ruma.test".to_string())).unwrap(),
|
||||
r#""io.ruma.test""#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancel_codes_deserialize_from_display_form() {
|
||||
assert_eq!(
|
||||
from_str::<CancelCode>(r#""m.user""#).unwrap(),
|
||||
CancelCode::User
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_cancel_codes_deserialize_from_display_form() {
|
||||
assert_eq!(
|
||||
from_str::<CancelCode>(r#""io.ruma.test""#).unwrap(),
|
||||
CancelCode::Custom("io.ruma.test".to_string())
|
||||
)
|
||||
}
|
||||
}
|
22
src/key/verification/key.rs
Normal file
22
src/key/verification/key.rs
Normal file
@ -0,0 +1,22 @@
|
||||
//! Types for the *m.key.verification.key* event.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
event! {
|
||||
/// Sends the ephemeral public key for a device to the partner device.
|
||||
///
|
||||
/// Typically sent as a to-device event.
|
||||
pub struct KeyEvent(KeyEventContent) {}
|
||||
}
|
||||
|
||||
/// The payload of an *m.key.verification.key* event.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct KeyEventContent {
|
||||
/// An opaque identifier for the verification process.
|
||||
///
|
||||
/// Must be the same as the one used for the *m.key.verification.start* message.
|
||||
pub transaction_id: String,
|
||||
|
||||
/// The device's ephemeral public key, encoded as unpadded Base64.
|
||||
pub key: String,
|
||||
}
|
29
src/key/verification/mac.rs
Normal file
29
src/key/verification/mac.rs
Normal file
@ -0,0 +1,29 @@
|
||||
//! Types for the *m.key.verification.mac* event.
|
||||
|
||||
use ruma_signatures::SignatureSet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
event! {
|
||||
/// Sends the MAC of a device's key to the partner device.
|
||||
///
|
||||
/// Typically sent as a to-device event.
|
||||
pub struct MacEvent(MacEventContent) {}
|
||||
}
|
||||
|
||||
/// The payload for an *m.key.verification.mac* event.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct MacEventContent {
|
||||
/// An opaque identifier for the verification process.
|
||||
///
|
||||
/// Must be the same as the one used for the *m.key.verification.start* message.
|
||||
pub transaction_id: String,
|
||||
|
||||
/// 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: SignatureSet,
|
||||
|
||||
/// The MAC of the comma-separated, sorted, list of key IDs given in the `mac` property, encoded
|
||||
/// as unpadded Base64.
|
||||
pub keys: String,
|
||||
}
|
34
src/key/verification/request.rs
Normal file
34
src/key/verification/request.rs
Normal file
@ -0,0 +1,34 @@
|
||||
//! Types for the *m.key.verification.request* event.
|
||||
|
||||
use ruma_identifiers::DeviceId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::VerificationMethod;
|
||||
|
||||
event! {
|
||||
/// Requests a key verification with another user's devices.
|
||||
///
|
||||
/// Typically sent as a to-device event.
|
||||
pub struct RequestEvent(RequestEventContent) {}
|
||||
}
|
||||
|
||||
/// The payload of an *m.key.verification.request* event.
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct RequestEventContent {
|
||||
/// The device ID which is initiating the request.
|
||||
pub from_device: DeviceId,
|
||||
|
||||
/// An opaque identifier for the verification request.
|
||||
///
|
||||
/// Must be unique with respect to the devices involved.
|
||||
pub transaction_id: String,
|
||||
|
||||
/// The verification methods supported by the sender.
|
||||
pub methods: Vec<VerificationMethod>,
|
||||
|
||||
/// The POSIX timestamp in milliseconds for when the request was made.
|
||||
///
|
||||
/// If the request is in the future by more than 5 minutes or more than 10 minutes in the past,
|
||||
/// the message should be ignored by the receiver.
|
||||
pub timestamp: u64,
|
||||
}
|
173
src/key/verification/start.rs
Normal file
173
src/key/verification/start.rs
Normal file
@ -0,0 +1,173 @@
|
||||
//! Types for the *m.key.verification.start* event.
|
||||
|
||||
use ruma_identifiers::DeviceId;
|
||||
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde_json::{from_value, Value};
|
||||
|
||||
use super::{
|
||||
HashAlgorithm, KeyAgreementProtocol, MessageAuthenticationCode, ShortAuthenticationString,
|
||||
VerificationMethod,
|
||||
};
|
||||
|
||||
event! {
|
||||
/// Begins an SAS key verification process.
|
||||
///
|
||||
/// Typically sent as a to-device event.
|
||||
pub struct StartEvent(StartEventContent) {}
|
||||
}
|
||||
|
||||
/// The payload of an *m.key.verification.start* event.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum StartEventContent {
|
||||
/// The *m.sas.v1* verification method.
|
||||
MSasV1(MSasV1Content),
|
||||
|
||||
/// Additional variants may be added in the future and will not be considered breaking changes
|
||||
/// to `ruma-events`.
|
||||
#[doc(hidden)]
|
||||
__Nonexhaustive,
|
||||
}
|
||||
|
||||
/// The payload of an *m.key.verification.start* event using the *m.sas.v1* method.
|
||||
#[derive(Clone, Debug, Serialize, PartialEq, Deserialize)]
|
||||
pub struct MSasV1Content {
|
||||
/// The device ID which is initiating the process.
|
||||
pub from_device: DeviceId,
|
||||
|
||||
/// An opaque identifier for the verification process.
|
||||
///
|
||||
/// Must be unique with respect to the devices involved. Must be the same as the
|
||||
/// `transaction_id` given in the *m.key.verification.request* if this process is originating
|
||||
/// from a request.
|
||||
pub transaction_id: String,
|
||||
|
||||
/// The verification method to use.
|
||||
///
|
||||
/// Must be `m.sas.v1`.
|
||||
pub method: VerificationMethod,
|
||||
|
||||
/// Optional method to use to verify the other user's key with.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub next_method: Option<VerificationMethod>,
|
||||
|
||||
/// The key agreement protocols the sending device understands.
|
||||
///
|
||||
/// Must include at least `curve25519`.
|
||||
pub key_agreement_protocols: Vec<KeyAgreementProtocol>,
|
||||
|
||||
/// The hash methods the sending device understands.
|
||||
///
|
||||
/// Must include at least `sha256`.
|
||||
pub hashes: Vec<HashAlgorithm>,
|
||||
|
||||
/// The message authentication codes that the sending device understands.
|
||||
///
|
||||
/// Must include at least `hkdf-hmac-sha256`.
|
||||
pub message_authentication_codes: Vec<MessageAuthenticationCode>,
|
||||
|
||||
/// The SAS methods the sending device (and the sending device's user) understands.
|
||||
///
|
||||
/// Must include at least `decimal`. Optionally can include `emoji`.
|
||||
pub short_authentication_string: Vec<ShortAuthenticationString>,
|
||||
}
|
||||
|
||||
impl Serialize for StartEventContent {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
match *self {
|
||||
StartEventContent::MSasV1(ref content) => content.serialize(serializer),
|
||||
_ => panic!("Attempted to serialize __Nonexhaustive variant."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for StartEventContent {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let value: Value = Deserialize::deserialize(deserializer)?;
|
||||
|
||||
let method_value = match value.get("method") {
|
||||
Some(value) => value.clone(),
|
||||
None => return Err(D::Error::missing_field("method")),
|
||||
};
|
||||
|
||||
let method = match from_value::<VerificationMethod>(method_value.clone()) {
|
||||
Ok(method) => method,
|
||||
Err(error) => return Err(D::Error::custom(error.to_string())),
|
||||
};
|
||||
|
||||
match method {
|
||||
VerificationMethod::MSasV1 => {
|
||||
let content = match from_value::<MSasV1Content>(value) {
|
||||
Ok(content) => content,
|
||||
Err(error) => return Err(D::Error::custom(error.to_string())),
|
||||
};
|
||||
|
||||
Ok(StartEventContent::MSasV1(content))
|
||||
}
|
||||
VerificationMethod::__Nonexhaustive => Err(D::Error::custom(
|
||||
"Attempted to deserialize __Nonexhaustive variant.",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json::{from_str, to_string};
|
||||
|
||||
use super::{
|
||||
HashAlgorithm, KeyAgreementProtocol, MSasV1Content, MessageAuthenticationCode,
|
||||
ShortAuthenticationString, StartEventContent, VerificationMethod,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn serializtion() {
|
||||
let key_verification_start_content = StartEventContent::MSasV1(MSasV1Content {
|
||||
from_device: "123".to_string(),
|
||||
transaction_id: "456".to_string(),
|
||||
method: VerificationMethod::MSasV1,
|
||||
next_method: None,
|
||||
hashes: vec![HashAlgorithm::Sha256],
|
||||
key_agreement_protocols: vec![KeyAgreementProtocol::Curve25519],
|
||||
message_authentication_codes: vec![MessageAuthenticationCode::HkdfHmacSha256],
|
||||
short_authentication_string: vec![ShortAuthenticationString::Decimal],
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
to_string(&key_verification_start_content).unwrap(),
|
||||
r#"{"from_device":"123","transaction_id":"456","method":"m.sas.v1","key_agreement_protocols":["curve25519"],"hashes":["sha256"],"message_authentication_codes":["hkdf-hmac-sha256"],"short_authentication_string":["decimal"]}"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialization() {
|
||||
let key_verification_start_content = StartEventContent::MSasV1(MSasV1Content {
|
||||
from_device: "123".to_string(),
|
||||
transaction_id: "456".to_string(),
|
||||
method: VerificationMethod::MSasV1,
|
||||
next_method: None,
|
||||
hashes: vec![HashAlgorithm::Sha256],
|
||||
key_agreement_protocols: vec![KeyAgreementProtocol::Curve25519],
|
||||
message_authentication_codes: vec![MessageAuthenticationCode::HkdfHmacSha256],
|
||||
short_authentication_string: vec![ShortAuthenticationString::Decimal],
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
from_str::<StartEventContent>(
|
||||
r#"{"from_device":"123","transaction_id":"456","method":"m.sas.v1","hashes":["sha256"],"key_agreement_protocols":["curve25519"],"message_authentication_codes":["hkdf-hmac-sha256"],"short_authentication_string":["decimal"]}"#
|
||||
)
|
||||
.unwrap(),
|
||||
key_verification_start_content
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialization_failure() {
|
||||
assert!(from_str::<StartEventContent>(r#"{"from_device":"123"}"#).is_err());
|
||||
}
|
||||
}
|
117
src/lib.rs
117
src/lib.rs
@ -118,11 +118,16 @@ pub mod collections {
|
||||
pub mod only;
|
||||
}
|
||||
pub mod direct;
|
||||
pub mod dummy;
|
||||
pub mod forwarded_room_key;
|
||||
pub mod fully_read;
|
||||
pub mod ignored_user_list;
|
||||
pub mod key;
|
||||
pub mod presence;
|
||||
pub mod receipt;
|
||||
pub mod room;
|
||||
pub mod room_key;
|
||||
pub mod room_key_request;
|
||||
pub mod sticker;
|
||||
pub mod stripped;
|
||||
pub mod tag;
|
||||
@ -411,6 +416,84 @@ impl<'de> Deserialize<'de> for EventType {
|
||||
}
|
||||
}
|
||||
|
||||
/// An encryption algorithm to be used to encrypt messages sent to a room.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum Algorithm {
|
||||
/// Olm version 1 using Curve25519, AES-256, and SHA-256.
|
||||
OlmV1Curve25519AesSha2,
|
||||
|
||||
/// Megolm version 1 using AES-256 and SHA-256.
|
||||
MegolmV1AesSha2,
|
||||
|
||||
/// Any algorithm that is not part of the specification.
|
||||
Custom(String),
|
||||
|
||||
/// Additional variants may be added in the future and will not be considered breaking changes
|
||||
/// to `ruma-events`.
|
||||
#[doc(hidden)]
|
||||
__Nonexhaustive,
|
||||
}
|
||||
|
||||
impl Display for Algorithm {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
let algorithm_str = match *self {
|
||||
Algorithm::OlmV1Curve25519AesSha2 => "m.olm.v1.curve25519-aes-sha2",
|
||||
Algorithm::MegolmV1AesSha2 => "m.megolm.v1.aes-sha2",
|
||||
Algorithm::Custom(ref algorithm) => algorithm,
|
||||
Algorithm::__Nonexhaustive => {
|
||||
panic!("__Nonexhaustive enum variant is not intended for use.")
|
||||
}
|
||||
};
|
||||
|
||||
write!(f, "{}", algorithm_str)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for Algorithm {
|
||||
fn from(s: &'a str) -> Algorithm {
|
||||
match s {
|
||||
"m.olm.v1.curve25519-aes-sha2" => Algorithm::OlmV1Curve25519AesSha2,
|
||||
"m.megolm.v1.aes-sha2" => Algorithm::MegolmV1AesSha2,
|
||||
algorithm => Algorithm::Custom(algorithm.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Algorithm {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Algorithm {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct CancelCodeVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for CancelCodeVisitor {
|
||||
type Value = Algorithm;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(formatter, "an encryption algorithm code as a string")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: SerdeError,
|
||||
{
|
||||
Ok(Algorithm::from(v))
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_str(CancelCodeVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
/// Serde deserialization decorator to map empty Strings to None,
|
||||
/// and forward non-empty Strings to the Deserialize implementation for T.
|
||||
/// Useful for the typical
|
||||
@ -445,7 +528,7 @@ fn default_true() -> bool {
|
||||
mod tests {
|
||||
use serde_json::{from_str, to_string};
|
||||
|
||||
use super::EventType;
|
||||
use super::{Algorithm, EventType};
|
||||
|
||||
#[test]
|
||||
fn event_types_serialize_to_display_form() {
|
||||
@ -478,4 +561,36 @@ mod tests {
|
||||
EventType::Custom("io.ruma.test".to_string())
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn algorithms_serialize_to_display_form() {
|
||||
assert_eq!(
|
||||
to_string(&Algorithm::MegolmV1AesSha2).unwrap(),
|
||||
r#""m.megolm.v1.aes-sha2""#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_algorithms_serialize_to_display_form() {
|
||||
assert_eq!(
|
||||
to_string(&Algorithm::Custom("io.ruma.test".to_string())).unwrap(),
|
||||
r#""io.ruma.test""#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn algorithms_deserialize_from_display_form() {
|
||||
assert_eq!(
|
||||
from_str::<Algorithm>(r#""m.megolm.v1.aes-sha2""#).unwrap(),
|
||||
Algorithm::MegolmV1AesSha2
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_algorithms_deserialize_from_display_form() {
|
||||
assert_eq!(
|
||||
from_str::<Algorithm>(r#""io.ruma.test""#).unwrap(),
|
||||
Algorithm::Custom("io.ruma.test".to_string())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,8 @@ pub mod aliases;
|
||||
pub mod avatar;
|
||||
pub mod canonical_alias;
|
||||
pub mod create;
|
||||
pub mod encrypted;
|
||||
pub mod encryption;
|
||||
pub mod guest_access;
|
||||
pub mod history_visibility;
|
||||
pub mod join_rules;
|
||||
|
184
src/room/encrypted.rs
Normal file
184
src/room/encrypted.rs
Normal file
@ -0,0 +1,184 @@
|
||||
//! Types for the *m.room.encrypted* event.
|
||||
|
||||
use ruma_identifiers::DeviceId;
|
||||
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde_json::{from_value, Value};
|
||||
|
||||
use crate::Algorithm;
|
||||
|
||||
room_event! {
|
||||
/// This event type is used when sending encrypted events.
|
||||
///
|
||||
/// This type is to be used within a room. For a to-device event, use `EncryptedEventContent`
|
||||
/// directly.
|
||||
pub struct EncryptedEvent(EncryptedEventContent) {}
|
||||
}
|
||||
|
||||
/// The payload of an *m.room.encrypted* event.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum EncryptedEventContent {
|
||||
/// An event encrypted with *m.olm.v1.curve25519-aes-sha2*.
|
||||
OlmV1Curve25519AesSha2(OlmV1Curve25519AesSha2Content),
|
||||
|
||||
/// An event encrypted with *m.megolm.v1.aes-sha2*.
|
||||
MegolmV1AesSha2(MegolmV1AesSha2Content),
|
||||
|
||||
/// Additional variants may be added in the future and will not be considered breaking changes
|
||||
/// to `ruma-events`.
|
||||
#[doc(hidden)]
|
||||
__Nonexhaustive,
|
||||
}
|
||||
|
||||
/// The payload of an *m.room.encrypted* event using the *m.olm.v1.curve25519-aes-sha2* algorithm.
|
||||
#[derive(Clone, Debug, Serialize, PartialEq, Deserialize)]
|
||||
pub struct OlmV1Curve25519AesSha2Content {
|
||||
/// The encryption algorithm used to encrypt this event.
|
||||
pub algorithm: Algorithm,
|
||||
|
||||
/// The encrypted content of the event.
|
||||
pub ciphertext: CiphertextInfo,
|
||||
|
||||
/// The Curve25519 key of the sender.
|
||||
pub sender_key: String,
|
||||
}
|
||||
|
||||
/// A map from the recipient Curve25519 identity key to ciphertext information.
|
||||
///
|
||||
/// Used for messages encrypted with the *m.olm.v1.curve25519-aes-sha2* algorithm.
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct CiphertextInfo {
|
||||
/// The encrypted payload.
|
||||
pub body: String,
|
||||
|
||||
/// The Olm message type.
|
||||
#[serde(rename = "type")]
|
||||
pub message_type: u64,
|
||||
}
|
||||
|
||||
/// The payload of an *m.room.encrypted* event using the *m.megolm.v1.aes-sha2* algorithm.
|
||||
#[derive(Clone, Debug, Serialize, PartialEq, Deserialize)]
|
||||
pub struct MegolmV1AesSha2Content {
|
||||
/// The encryption algorithm used to encrypt this event.
|
||||
pub algorithm: Algorithm,
|
||||
|
||||
/// The encrypted content of the event.
|
||||
pub ciphertext: String,
|
||||
|
||||
/// The Curve25519 key of the sender.
|
||||
pub sender_key: String,
|
||||
|
||||
/// The ID of the sending device.
|
||||
pub device_id: DeviceId,
|
||||
|
||||
/// The ID of the session used to encrypt the message.
|
||||
pub session_id: String,
|
||||
}
|
||||
|
||||
impl Serialize for EncryptedEventContent {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
match *self {
|
||||
EncryptedEventContent::OlmV1Curve25519AesSha2(ref content) => {
|
||||
content.serialize(serializer)
|
||||
}
|
||||
EncryptedEventContent::MegolmV1AesSha2(ref content) => content.serialize(serializer),
|
||||
_ => panic!("Attempted to serialize __Nonexhaustive variant."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for EncryptedEventContent {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let value: Value = Deserialize::deserialize(deserializer)?;
|
||||
|
||||
let method_value = match value.get("algorithm") {
|
||||
Some(value) => value.clone(),
|
||||
None => return Err(D::Error::missing_field("algorithm")),
|
||||
};
|
||||
|
||||
let method = match from_value::<Algorithm>(method_value.clone()) {
|
||||
Ok(method) => method,
|
||||
Err(error) => return Err(D::Error::custom(error.to_string())),
|
||||
};
|
||||
|
||||
match method {
|
||||
Algorithm::OlmV1Curve25519AesSha2 => {
|
||||
let content = match from_value::<OlmV1Curve25519AesSha2Content>(value) {
|
||||
Ok(content) => content,
|
||||
Err(error) => return Err(D::Error::custom(error.to_string())),
|
||||
};
|
||||
|
||||
Ok(EncryptedEventContent::OlmV1Curve25519AesSha2(content))
|
||||
}
|
||||
Algorithm::MegolmV1AesSha2 => {
|
||||
let content = match from_value::<MegolmV1AesSha2Content>(value) {
|
||||
Ok(content) => content,
|
||||
Err(error) => return Err(D::Error::custom(error.to_string())),
|
||||
};
|
||||
|
||||
Ok(EncryptedEventContent::MegolmV1AesSha2(content))
|
||||
}
|
||||
Algorithm::Custom(_) => Err(D::Error::custom(
|
||||
"Custom algorithms are not supported by `EncryptedEventContent`.",
|
||||
)),
|
||||
Algorithm::__Nonexhaustive => Err(D::Error::custom(
|
||||
"Attempted to deserialize __Nonexhaustive variant.",
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json::{from_str, to_string};
|
||||
|
||||
use super::{Algorithm, EncryptedEventContent, MegolmV1AesSha2Content};
|
||||
|
||||
#[test]
|
||||
fn serializtion() {
|
||||
let key_verification_start_content =
|
||||
EncryptedEventContent::MegolmV1AesSha2(MegolmV1AesSha2Content {
|
||||
algorithm: Algorithm::MegolmV1AesSha2,
|
||||
ciphertext: "ciphertext".to_string(),
|
||||
sender_key: "sender_key".to_string(),
|
||||
device_id: "device_id".to_string(),
|
||||
session_id: "session_id".to_string(),
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
to_string(&key_verification_start_content).unwrap(),
|
||||
r#"{"algorithm":"m.megolm.v1.aes-sha2","ciphertext":"ciphertext","sender_key":"sender_key","device_id":"device_id","session_id":"session_id"}"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialization() {
|
||||
let key_verification_start_content =
|
||||
EncryptedEventContent::MegolmV1AesSha2(MegolmV1AesSha2Content {
|
||||
algorithm: Algorithm::MegolmV1AesSha2,
|
||||
ciphertext: "ciphertext".to_string(),
|
||||
sender_key: "sender_key".to_string(),
|
||||
device_id: "device_id".to_string(),
|
||||
session_id: "session_id".to_string(),
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
from_str::<EncryptedEventContent>(
|
||||
r#"{"algorithm":"m.megolm.v1.aes-sha2","ciphertext":"ciphertext","sender_key":"sender_key","device_id":"device_id","session_id":"session_id"}"#
|
||||
)
|
||||
.unwrap(),
|
||||
key_verification_start_content
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialization_failure() {
|
||||
assert!(
|
||||
from_str::<EncryptedEventContent>(r#"{"algorithm":"m.megolm.v1.aes-sha2"}"#).is_err()
|
||||
);
|
||||
}
|
||||
}
|
29
src/room/encryption.rs
Normal file
29
src/room/encryption.rs
Normal file
@ -0,0 +1,29 @@
|
||||
//! Types for the *m.room.encryption* event.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::Algorithm;
|
||||
|
||||
state_event! {
|
||||
/// Defines how messages sent in this room should be encrypted.
|
||||
pub struct EncryptionEvent(EncryptionEventContent) {}
|
||||
}
|
||||
|
||||
/// The payload of an *m.room.encryption* event.
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct EncryptionEventContent {
|
||||
/// The encryption algorithm to be used to encrypt messages sent in this room.
|
||||
///
|
||||
/// Must be `m.megolm.v1.aes-sha2`.
|
||||
pub algorithm: Algorithm,
|
||||
|
||||
/// How long the session should be used before changing it.
|
||||
///
|
||||
/// 604800000 (a week) is the recommended default.
|
||||
pub rotation_period_ms: Option<u64>,
|
||||
|
||||
/// How many messages should be sent before changing the session.
|
||||
///
|
||||
/// 100 is the recommended default.
|
||||
pub rotation_period_msgs: Option<u64>,
|
||||
}
|
31
src/room_key.rs
Normal file
31
src/room_key.rs
Normal file
@ -0,0 +1,31 @@
|
||||
//! Types for the *m.room_key* event.
|
||||
|
||||
use ruma_identifiers::RoomId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::Algorithm;
|
||||
|
||||
event! {
|
||||
/// This event type is used to exchange keys for end-to-end encryption.
|
||||
///
|
||||
/// Typically it is encrypted as an *m.room.encrypted* event, then sent as a to-device event.
|
||||
pub struct RoomKeyEvent(RoomKeyEventContent) {}
|
||||
}
|
||||
|
||||
/// The payload of an *m.room_key* event.
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct RoomKeyEventContent {
|
||||
/// The encryption algorithm the key in this event is to be used with.
|
||||
///
|
||||
/// Must be `m.megolm.v1.aes-sha2`.
|
||||
pub algorithm: Algorithm,
|
||||
|
||||
/// The room where the key is used.
|
||||
pub room_id: RoomId,
|
||||
|
||||
/// The ID of the session that the key is for.
|
||||
pub session_id: String,
|
||||
|
||||
/// The key to be exchanged.
|
||||
pub session_key: String,
|
||||
}
|
73
src/room_key_request.rs
Normal file
73
src/room_key_request.rs
Normal file
@ -0,0 +1,73 @@
|
||||
//! Types for the *m.room_key_request* event.
|
||||
|
||||
use ruma_identifiers::{DeviceId, RoomId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::Algorithm;
|
||||
|
||||
event! {
|
||||
/// This event type is used to request keys for end-to-end encryption.
|
||||
///
|
||||
/// It is sent as an unencrypted to-device event.
|
||||
pub struct RoomKeyRequestEvent(RoomKeyRequestEventContent) {}
|
||||
}
|
||||
|
||||
/// The payload of an *m.room_key_request* event.
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct RoomKeyRequestEventContent {
|
||||
/// Whether this is a new key request or a cancellation of a previous request.
|
||||
pub action: Action,
|
||||
|
||||
/// Information about the requested key.
|
||||
///
|
||||
/// Required when action is `request`.
|
||||
pub body: Option<RequestedKeyInfo>,
|
||||
|
||||
/// ID of the device requesting the key.
|
||||
pub requesting_device_id: DeviceId,
|
||||
|
||||
/// A random string uniquely identifying the request for a key.
|
||||
///
|
||||
/// If the key is requested multiple times, it should be reused. It should also reused in order
|
||||
/// to cancel a request.
|
||||
pub request_id: String,
|
||||
}
|
||||
|
||||
/// A new key request or a cancellation of a previous request.
|
||||
#[derive(Clone, Copy, Deserialize, Debug, PartialEq, Serialize)]
|
||||
pub enum Action {
|
||||
/// Request a key.
|
||||
Request,
|
||||
|
||||
/// Cancel a request for a key.
|
||||
CancelRequest,
|
||||
|
||||
/// Additional variants may be added in the future and will not be considered breaking changes
|
||||
/// to `ruma-events`.
|
||||
#[doc(hidden)]
|
||||
#[serde(skip)]
|
||||
__Nonexhaustive,
|
||||
}
|
||||
|
||||
impl_enum! {
|
||||
Action {
|
||||
Request => "request",
|
||||
CancelRequest => "cancel_request",
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about a requested key.
|
||||
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct RequestedKeyInfo {
|
||||
/// The encryption algorithm the requested key in this event is to be used with.
|
||||
pub algorithm: Algorithm,
|
||||
|
||||
/// The room where the key 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,
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user