diff --git a/src/api/server_server.rs b/src/api/server_server.rs index 74eeac31..2c160c57 100644 --- a/src/api/server_server.rs +++ b/src/api/server_server.rs @@ -577,18 +577,22 @@ pub(crate) async fn get_server_version_route( // Response type for this endpoint is Json because we need to calculate a // signature for the response pub(crate) async fn get_server_keys_route() -> Result { + let keys: Vec<_> = [services().globals.keypair()] + .into_iter() + .chain(&services().globals.config.extra_key) + .collect(); let mut verify_keys: BTreeMap = BTreeMap::new(); - verify_keys.insert( - format!("ed25519:{}", services().globals.keypair().version()) - .try_into() - .expect("found invalid server signing keys in DB"), - VerifyKey { - key: Base64::new( - services().globals.keypair().public_key().to_vec(), - ), - }, - ); + for key in &keys { + verify_keys.insert( + format!("ed25519:{}", key.version()) + .try_into() + .expect("found invalid server signing keys in DB"), + VerifyKey { + key: Base64::new(key.public_key().to_vec()), + }, + ); + } let mut response = serde_json::from_slice( get_server_keys::v2::Response { server_key: Raw::new(&ServerSigningKeys { @@ -609,12 +613,14 @@ pub(crate) async fn get_server_keys_route() -> Result { ) .unwrap(); - ruma::signatures::sign_json( - services().globals.server_name().as_str(), - services().globals.keypair(), - &mut response, - ) - .unwrap(); + for key in &keys { + ruma::signatures::sign_json( + services().globals.server_name().as_str(), + *key, + &mut response, + ) + .unwrap(); + } Ok(Json(response)) } diff --git a/src/config.rs b/src/config.rs index 51761f85..08831915 100644 --- a/src/config.rs +++ b/src/config.rs @@ -6,8 +6,8 @@ use std::{ }; use once_cell::sync::Lazy; -use ruma::{OwnedServerName, RoomVersionId}; -use serde::Deserialize; +use ruma::{serde::Base64, signatures::Ed25519KeyPair, OwnedServerName, RoomVersionId}; +use serde::{Deserialize, Deserializer}; use crate::error; @@ -29,6 +29,8 @@ pub(crate) struct Config { #[serde(default = "default_listen")] pub(crate) listen: Vec, pub(crate) tls: Option, + #[serde(default, deserialize_with = "deserialize_keys_config")] + pub(crate) extra_key: Vec, /// The name of this homeserver /// @@ -69,6 +71,22 @@ pub(crate) struct Config { pub(crate) emergency_password: Option, } +fn deserialize_keys_config<'de, D>(de: D) -> Result, D::Error> where D: Deserializer<'de> { + use serde::de::Error; + + #[derive(Debug, Deserialize)] + struct RawConfig { + key: Base64, + version: String, + } + + let raw: Vec = Deserialize::deserialize(de)?; + raw + .into_iter() + .map(|r| Ed25519KeyPair::from_der(&r.key.into_inner(), r.version).map_err(D::Error::custom)) + .collect() +} + #[derive(Debug, Default, Deserialize)] pub(crate) struct ServerDiscovery { /// Server-server discovery configuration