diff --git a/crates/ruma-client-api/src/r0/backup.rs b/crates/ruma-client-api/src/r0/backup.rs index 703f1a23..d3b9b6cf 100644 --- a/crates/ruma-client-api/src/r0/backup.rs +++ b/crates/ruma-client-api/src/r0/backup.rs @@ -48,7 +48,7 @@ pub enum BackupAlgorithm { public_key: String, /// Signatures of the auth_data as Signed JSON. - signatures: BTreeMap>, + signatures: BTreeMap, String>>, }, } diff --git a/crates/ruma-client-api/src/r0/keys/claim_keys.rs b/crates/ruma-client-api/src/r0/keys/claim_keys.rs index aa28d55d..f4d27157 100644 --- a/crates/ruma-client-api/src/r0/keys/claim_keys.rs +++ b/crates/ruma-client-api/src/r0/keys/claim_keys.rs @@ -60,4 +60,4 @@ impl Response { } /// The one-time keys for a given device. -pub type OneTimeKeys = BTreeMap, BTreeMap>; +pub type OneTimeKeys = BTreeMap, BTreeMap, OneTimeKey>>; diff --git a/crates/ruma-client-api/src/r0/keys/upload_keys.rs b/crates/ruma-client-api/src/r0/keys/upload_keys.rs index 217b618a..7c6be7e4 100644 --- a/crates/ruma-client-api/src/r0/keys/upload_keys.rs +++ b/crates/ruma-client-api/src/r0/keys/upload_keys.rs @@ -27,7 +27,7 @@ ruma_api! { /// One-time public keys for "pre-key" messages. #[serde(skip_serializing_if = "Option::is_none")] - pub one_time_keys: Option>, + pub one_time_keys: Option, OneTimeKey>>, } response: { diff --git a/crates/ruma-common/src/encryption.rs b/crates/ruma-common/src/encryption.rs index d813764e..39005391 100644 --- a/crates/ruma-common/src/encryption.rs +++ b/crates/ruma-common/src/encryption.rs @@ -25,10 +25,10 @@ pub struct DeviceKeys { pub algorithms: Vec, /// Public identity keys. - pub keys: BTreeMap, + pub keys: BTreeMap, String>, /// Signatures for the device key object. - pub signatures: BTreeMap>, + pub signatures: BTreeMap, String>>, /// Additional data added to the device key information by intermediate servers, and /// not covered by the signatures. @@ -43,8 +43,8 @@ impl DeviceKeys { user_id: UserId, device_id: Box, algorithms: Vec, - keys: BTreeMap, - signatures: BTreeMap>, + keys: BTreeMap, String>, + signatures: BTreeMap, String>>, ) -> Self { Self { user_id, device_id, algorithms, keys, signatures, unsigned: Default::default() } } @@ -72,7 +72,7 @@ impl UnsignedDeviceInfo { } /// Signatures for a `SignedKey` object. -pub type SignedKeySignatures = BTreeMap>; +pub type SignedKeySignatures = BTreeMap, String>>; /// A key for the SignedCurve25519 algorithm #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/crates/ruma-federation-api/src/keys/claim_keys/v1.rs b/crates/ruma-federation-api/src/keys/claim_keys/v1.rs index b8cdaaea..59f89a20 100644 --- a/crates/ruma-federation-api/src/keys/claim_keys/v1.rs +++ b/crates/ruma-federation-api/src/keys/claim_keys/v1.rs @@ -47,7 +47,8 @@ impl Response { pub type OneTimeKeyClaims = BTreeMap, DeviceKeyAlgorithm>>; /// One time keys for use in pre-key messages -pub type OneTimeKeys = BTreeMap, BTreeMap>>; +pub type OneTimeKeys = + BTreeMap, BTreeMap, OneTimeKey>>>; /// A key and its signature #[derive(Debug, Clone, Serialize, Deserialize)] @@ -57,12 +58,15 @@ pub struct KeyObject { pub key: String, /// Signature of the key object. - pub signatures: BTreeMap>, + pub signatures: BTreeMap, String>>, } impl KeyObject { /// Creates a new `KeyObject` with the given key and signatures. - pub fn new(key: String, signatures: BTreeMap>) -> Self { + pub fn new( + key: String, + signatures: BTreeMap, String>>, + ) -> Self { Self { key, signatures } } } diff --git a/crates/ruma-identifiers-macros/src/lib.rs b/crates/ruma-identifiers-macros/src/lib.rs index 65a6a356..76f4defa 100644 --- a/crates/ruma-identifiers-macros/src/lib.rs +++ b/crates/ruma-identifiers-macros/src/lib.rs @@ -31,7 +31,7 @@ pub fn device_key_id(input: TokenStream) -> TokenStream { assert!(device_key_id::validate(&id.value()).is_ok(), "Invalid device key id"); let output = quote! { - <#dollar_crate::DeviceKeyId as ::std::convert::TryFrom<&str>>::try_from(#id).unwrap() + <&#dollar_crate::DeviceKeyId as ::std::convert::TryFrom<&str>>::try_from(#id).unwrap() }; output.into() diff --git a/crates/ruma-identifiers-validation/src/device_key_id.rs b/crates/ruma-identifiers-validation/src/device_key_id.rs index 287a158c..ca22f2fa 100644 --- a/crates/ruma-identifiers-validation/src/device_key_id.rs +++ b/crates/ruma-identifiers-validation/src/device_key_id.rs @@ -1,10 +1,12 @@ -use std::num::NonZeroU8; - use crate::Error; -pub fn validate(s: &str) -> Result { - let colon_idx = NonZeroU8::new(s.find(':').ok_or(Error::MissingDelimiter)? as u8) - .ok_or(Error::InvalidKeyAlgorithm)?; +pub fn validate(s: &str) -> Result<(), Error> { + let colon_idx = s.find(':').ok_or(Error::MissingDelimiter)?; - Ok(colon_idx) + if colon_idx == 0 { + Err(Error::InvalidKeyAlgorithm) + } else { + // Any non-empty string is accepted as a key algorithm for forwards compatibility + Ok(()) + } } diff --git a/crates/ruma-identifiers/src/device_key_id.rs b/crates/ruma-identifiers/src/device_key_id.rs index d250986c..7af7d118 100644 --- a/crates/ruma-identifiers/src/device_key_id.rs +++ b/crates/ruma-identifiers/src/device_key_id.rs @@ -1,25 +1,17 @@ //! Identifiers for device keys for end-to-end encryption. -use std::{convert::TryInto, fmt, num::NonZeroU8}; +use ruma_identifiers_validation::device_key_id::validate; use crate::{crypto_algorithms::DeviceKeyAlgorithm, DeviceId}; -/// A key algorithm and a device id, combined with a ':'. -#[derive(Clone)] -pub struct DeviceKeyId { - full_id: Box, - colon_idx: NonZeroU8, -} - -impl fmt::Debug for DeviceKeyId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.full_id.fmt(f) - } +opaque_identifier_validated! { + /// A key algorithm and a device id, combined with a ':'. + pub type DeviceKeyId [ validate ]; } impl DeviceKeyId { /// Create a `DeviceKeyId` from a `DeviceKeyAlgorithm` and a `DeviceId`. - pub fn from_parts(algorithm: DeviceKeyAlgorithm, device_id: &DeviceId) -> Self { + pub fn from_parts(algorithm: DeviceKeyAlgorithm, device_id: &DeviceId) -> Box { let algorithm: &str = algorithm.as_ref(); let device_id: &str = device_id.as_ref(); @@ -28,34 +20,24 @@ impl DeviceKeyId { res.push(':'); res.push_str(device_id); - let colon_idx = - NonZeroU8::new(algorithm.len().try_into().expect("no algorithm name len > 255")) - .expect("no empty algorithm name"); - - DeviceKeyId { full_id: res.into(), colon_idx } + Self::from_owned(res.into()) } /// Returns key algorithm of the device key ID. pub fn algorithm(&self) -> DeviceKeyAlgorithm { - self.full_id[..self.colon_idx.get() as usize].into() + self.as_str()[..self.colon_idx()].into() } /// Returns device ID of the device key ID. pub fn device_id(&self) -> &DeviceId { - (&self.full_id[self.colon_idx.get() as usize + 1..]).into() + self.as_str()[self.colon_idx() + 1..].into() + } + + fn colon_idx(&self) -> usize { + self.as_str().find(':').unwrap() } } -fn try_from(key_id: S) -> Result -where - S: AsRef + Into>, -{ - let colon_idx = ruma_identifiers_validation::device_key_id::validate(key_id.as_ref())?; - Ok(DeviceKeyId { full_id: key_id.into(), colon_idx }) -} - -common_impls!(DeviceKeyId, try_from, "Device key ID with algorithm and device ID"); - #[cfg(test)] mod tests { use std::convert::TryFrom; @@ -66,9 +48,8 @@ mod tests { #[test] fn convert_device_key_id() { assert_eq!( - DeviceKeyId::try_from("ed25519:JLAFKJWSCS") - .expect("Failed to create device key ID.") - .as_ref(), + <&DeviceKeyId>::try_from("ed25519:JLAFKJWSCS") + .expect("Failed to create device key ID."), "ed25519:JLAFKJWSCS" ); } @@ -76,7 +57,7 @@ mod tests { #[cfg(feature = "serde")] #[test] fn serialize_device_key_id() { - let device_key_id = DeviceKeyId::try_from("ed25519:JLAFKJWSCS").unwrap(); + let device_key_id = <&DeviceKeyId>::try_from("ed25519:JLAFKJWSCS").unwrap(); let serialized = serde_json::to_value(device_key_id).unwrap(); assert_eq!(serialized, serde_json::json!("ed25519:JLAFKJWSCS")); @@ -85,40 +66,43 @@ mod tests { #[cfg(feature = "serde")] #[test] fn deserialize_device_key_id() { - let deserialized: DeviceKeyId = + let deserialized: Box = serde_json::from_value(serde_json::json!("ed25519:JLAFKJWSCS")).unwrap(); - let expected = DeviceKeyId::try_from("ed25519:JLAFKJWSCS").unwrap(); + let expected = <&DeviceKeyId>::try_from("ed25519:JLAFKJWSCS").unwrap(); assert_eq!(deserialized, expected); } #[test] fn missing_key_algorithm() { - assert_eq!(DeviceKeyId::try_from(":JLAFKJWSCS").unwrap_err(), Error::InvalidKeyAlgorithm); + assert_eq!( + <&DeviceKeyId>::try_from(":JLAFKJWSCS").unwrap_err(), + Error::InvalidKeyAlgorithm + ); } #[test] fn missing_delimiter() { assert_eq!( - DeviceKeyId::try_from("ed25519|JLAFKJWSCS").unwrap_err(), + <&DeviceKeyId>::try_from("ed25519|JLAFKJWSCS").unwrap_err(), Error::MissingDelimiter, ); } #[test] fn empty_device_id_ok() { - assert!(DeviceKeyId::try_from("ed25519:").is_ok()); + assert!(<&DeviceKeyId>::try_from("ed25519:").is_ok()); } #[test] fn valid_key_algorithm() { - let device_key_id = DeviceKeyId::try_from("ed25519:JLAFKJWSCS").unwrap(); + let device_key_id = <&DeviceKeyId>::try_from("ed25519:JLAFKJWSCS").unwrap(); assert_eq!(device_key_id.algorithm(), DeviceKeyAlgorithm::Ed25519); } #[test] fn valid_device_id() { - let device_key_id = DeviceKeyId::try_from("ed25519:JLAFKJWSCS").unwrap(); + let device_key_id = <&DeviceKeyId>::try_from("ed25519:JLAFKJWSCS").unwrap(); assert_eq!(device_key_id.device_id(), "JLAFKJWSCS"); } }