identifiers: Make DeviceKeyId a type alias of KeyId

This commit is contained in:
Kévin Commaille 2024-10-10 11:44:41 +02:00 committed by strawberry
parent 7f8f89eff7
commit 35da79a26e
9 changed files with 27 additions and 156 deletions

View File

@ -36,6 +36,9 @@ Breaking changes:
`CrossSigningKey`'s `signatures`.
- Use `OwnedDeviceSigningKeyId` instead of `OwnedDeviceKeyId` to identify
signing keys in `SignedKey`'s `signatures`.
- `(Owned)DeviceKeyId` is now a type alias of `(Owned)KeyId`.
- Remove the `(owned_)device_key_id` macro, instead use
`DeviceKeyId::from_parts`.
Improvements:

View File

@ -24,13 +24,13 @@ pub use self::{
SigningKeyAlgorithm,
},
device_id::{DeviceId, OwnedDeviceId},
device_key_id::{DeviceKeyId, OwnedDeviceKeyId},
event_id::{EventId, OwnedEventId},
key_id::{
CrossSigningKeyId, CrossSigningOrDeviceSigningKeyId, DeviceSigningKeyId, KeyAlgorithm,
KeyId, OneTimeKeyId, OwnedCrossSigningKeyId, OwnedCrossSigningOrDeviceSigningKeyId,
OwnedDeviceSigningKeyId, OwnedKeyId, OwnedOneTimeKeyId, OwnedServerSigningKeyId,
OwnedSigningKeyId, ServerSigningKeyId, SigningKeyId,
CrossSigningKeyId, CrossSigningOrDeviceSigningKeyId, DeviceKeyId, DeviceSigningKeyId,
KeyAlgorithm, KeyId, OneTimeKeyId, OwnedCrossSigningKeyId,
OwnedCrossSigningOrDeviceSigningKeyId, OwnedDeviceKeyId, OwnedDeviceSigningKeyId,
OwnedKeyId, OwnedOneTimeKeyId, OwnedServerSigningKeyId, OwnedSigningKeyId,
ServerSigningKeyId, SigningKeyId,
},
matrix_uri::{MatrixToUri, MatrixUri},
mxc_uri::{Mxc, MxcUri, OwnedMxcUri},
@ -57,7 +57,6 @@ mod base64_public_key_or_device_id;
mod client_secret;
mod crypto_algorithms;
mod device_id;
mod device_key_id;
mod event_id;
mod key_id;
mod mxc_uri;
@ -118,24 +117,8 @@ macro_rules! owned_device_id {
#[doc(hidden)]
pub mod __private_macros {
pub use ruma_macros::{
base64_public_key, device_key_id, event_id, mxc_uri, room_alias_id, room_id,
room_version_id, server_name, server_signing_key_version, user_id,
};
}
/// Compile-time checked [`DeviceKeyId`] construction.
#[macro_export]
macro_rules! device_key_id {
($s:literal) => {
$crate::__private_macros::device_key_id!($crate, $s)
};
}
/// Compile-time checked [`OwnedDeviceKeyId`] construction.
#[macro_export]
macro_rules! owned_device_key_id {
($s:literal) => {
$crate::device_key_id!($s).to_owned()
base64_public_key, event_id, mxc_uri, room_alias_id, room_id, room_version_id, server_name,
server_signing_key_version, user_id,
};
}

View File

@ -1,102 +0,0 @@
//! Identifiers for device keys for end-to-end encryption.
use ruma_macros::IdZst;
use super::{crypto_algorithms::DeviceKeyAlgorithm, DeviceId};
/// A key algorithm and a device id, combined with a ':'.
#[repr(transparent)]
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, IdZst)]
#[ruma_id(validate = ruma_identifiers_validation::device_key_id::validate)]
pub struct DeviceKeyId(str);
impl DeviceKeyId {
/// Create a `DeviceKeyId` from a `DeviceKeyAlgorithm` and a `DeviceId`.
pub fn from_parts(algorithm: DeviceKeyAlgorithm, device_id: &DeviceId) -> OwnedDeviceKeyId {
let algorithm: &str = algorithm.as_ref();
let device_id: &str = device_id.as_ref();
let mut res = String::with_capacity(algorithm.len() + 1 + device_id.len());
res.push_str(algorithm);
res.push(':');
res.push_str(device_id);
Self::from_borrowed(&res).to_owned()
}
/// Returns key algorithm of the device key ID.
pub fn algorithm(&self) -> DeviceKeyAlgorithm {
self.as_str()[..self.colon_idx()].into()
}
/// Returns device ID of the device key ID.
pub fn device_id(&self) -> &DeviceId {
self.as_str()[self.colon_idx() + 1..].into()
}
fn colon_idx(&self) -> usize {
self.as_str().find(':').unwrap()
}
}
#[cfg(test)]
mod tests {
use super::{DeviceKeyId, OwnedDeviceKeyId};
use crate::identifiers::{crypto_algorithms::DeviceKeyAlgorithm, IdParseError};
#[test]
fn convert_device_key_id() {
assert_eq!(
<&DeviceKeyId>::try_from("ed25519:JLAFKJWSCS")
.expect("Failed to create device key ID."),
"ed25519:JLAFKJWSCS"
);
}
#[test]
fn serialize_device_key_id() {
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"));
}
#[test]
fn deserialize_device_key_id() {
let deserialized: OwnedDeviceKeyId =
serde_json::from_value(serde_json::json!("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(), IdParseError::Empty);
}
#[test]
fn missing_delimiter() {
assert_eq!(
<&DeviceKeyId>::try_from("ed25519|JLAFKJWSCS").unwrap_err(),
IdParseError::MissingColon,
);
}
#[test]
fn empty_device_id_ok() {
<&DeviceKeyId>::try_from("ed25519:").unwrap();
}
#[test]
fn valid_key_algorithm() {
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();
assert_eq!(device_key_id.device_id(), "JLAFKJWSCS");
}
}

View File

@ -8,7 +8,7 @@ use ruma_macros::IdZst;
use super::{
crypto_algorithms::SigningKeyAlgorithm, Base64PublicKey, Base64PublicKeyOrDeviceId, DeviceId,
KeyName, OneTimeKeyAlgorithm, OneTimeKeyName, ServerSigningKeyVersion,
DeviceKeyAlgorithm, KeyName, OneTimeKeyAlgorithm, OneTimeKeyName, ServerSigningKeyVersion,
};
/// A key algorithm and key name delimited by a colon.
@ -95,6 +95,16 @@ pub type CrossSigningOrDeviceSigningKeyId = SigningKeyId<Base64PublicKeyOrDevice
/// [device signing]: https://spec.matrix.org/latest/client-server-api/#device-keys
pub type OwnedCrossSigningOrDeviceSigningKeyId = OwnedSigningKeyId<Base64PublicKeyOrDeviceId>;
/// Algorithm + key name for [device keys].
///
/// [device keys]: https://spec.matrix.org/latest/client-server-api/#device-keys
pub type DeviceKeyId = KeyId<DeviceKeyAlgorithm, DeviceId>;
/// Algorithm + key name for [device keys].
///
/// [device keys]: https://spec.matrix.org/latest/client-server-api/#device-keys
pub type OwnedDeviceKeyId = OwnedKeyId<DeviceKeyAlgorithm, DeviceId>;
/// Algorithm + key name for [one-time and fallback keys].
///
/// [one-time and fallback keys]: https://spec.matrix.org/latest/client-server-api/#one-time-and-fallback-keys
@ -138,4 +148,6 @@ pub trait KeyAlgorithm: for<'a> From<&'a str> + AsRef<str> {}
impl KeyAlgorithm for SigningKeyAlgorithm {}
impl KeyAlgorithm for DeviceKeyAlgorithm {}
impl KeyAlgorithm for OneTimeKeyAlgorithm {}

View File

@ -1,5 +1,4 @@
fn main() {
_ = ruma_common::device_key_id!("ed25519:JLAFKJWSCS");
_ = ruma_common::event_id!("$39hvsi03hlne:example.com");
_ = ruma_common::event_id!("$acR1l0raoZnm60CBwAVgqbZqoO/mYU81xysh1u7XcJk");
_ = ruma_common::mxc_uri!("mxc://myserver.fish/sdfdsfsdfsdfgsdfsd");

View File

@ -7,6 +7,8 @@ Breaking changes:
are not only server signing key versions.
- The `compat-key-id` cargo feature was renamed to
`compat-server-signing-key-version`.
- Remove the `device_key_id` module. `DeviceKeyId` is now validated with
`key_id::validate`.
Improvements:

View File

@ -1,12 +0,0 @@
use crate::Error;
pub fn validate(s: &str) -> Result<(), Error> {
let colon_idx = s.find(':').ok_or(Error::MissingColon)?;
if colon_idx == 0 {
Err(Error::Empty)
} else {
// Any non-empty string is accepted as a key algorithm for forwards compatibility
Ok(())
}
}

View File

@ -3,7 +3,6 @@
pub mod base64_public_key;
pub mod client_secret;
pub mod device_key_id;
pub mod error;
pub mod event_id;
pub mod key_id;

View File

@ -15,8 +15,8 @@ use proc_macro::TokenStream;
use proc_macro2 as pm2;
use quote::quote;
use ruma_identifiers_validation::{
base64_public_key, device_key_id, event_id, mxc_uri, room_alias_id, room_id, room_version_id,
server_name, server_signing_key_version, user_id,
base64_public_key, event_id, mxc_uri, room_alias_id, room_id, room_version_id, server_name,
server_signing_key_version, user_id,
};
use syn::{parse_macro_input, DeriveInput, ItemEnum, ItemStruct};
@ -146,19 +146,6 @@ pub fn derive_id_zst(input: TokenStream) -> TokenStream {
expand_id_zst(input).unwrap_or_else(syn::Error::into_compile_error).into()
}
/// Compile-time checked `DeviceKeyId` construction.
#[proc_macro]
pub fn device_key_id(input: TokenStream) -> TokenStream {
let IdentifierInput { dollar_crate, id } = parse_macro_input!(input as IdentifierInput);
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()
};
output.into()
}
/// Compile-time checked `EventId` construction.
#[proc_macro]
pub fn event_id(input: TokenStream) -> TokenStream {