mirror of
https://github.com/element-hq/synapse.git
synced 2026-05-14 14:45:10 +00:00
feat: Port SignatureListItem to Rust
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This file is licensed under the Affero General Public License (AGPL) version 3.
|
||||
*
|
||||
* Copyright (C) 2026 Element Creations Ltd
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* See the GNU Affero General Public License for more details:
|
||||
* <https://www.gnu.org/licenses/agpl-3.0.html>.
|
||||
*
|
||||
* Originally licensed under the Apache License, Version 2.0:
|
||||
* <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||
*
|
||||
* [This file includes modifications made by Element Creations Ltd]
|
||||
*/
|
||||
|
||||
use pyo3::{
|
||||
pyclass, pymethods,
|
||||
types::{PyAnyMethods, PyModule, PyModuleMethods},
|
||||
Bound, Py, PyAny, PyResult, Python,
|
||||
};
|
||||
|
||||
pub fn register_module(py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
|
||||
let child_module = PyModule::new(py, "e2e_keys")?;
|
||||
child_module.add_class::<SignatureListItem>()?;
|
||||
|
||||
m.add_submodule(&child_module)?;
|
||||
|
||||
py.import("sys")?
|
||||
.getattr("modules")?
|
||||
.set_item("synapse.synapse_rust.e2e_keys", child_module)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// A pending cross-signing signature.
|
||||
#[derive(Debug)]
|
||||
#[pyclass(frozen)]
|
||||
pub struct SignatureListItem {
|
||||
/// Full key ID of the signing key, e.g. `"ed25519:ABCDEF"`.
|
||||
#[pyo3(get)]
|
||||
pub signing_key_id: String,
|
||||
|
||||
/// User whose key was signed.
|
||||
#[pyo3(get)]
|
||||
pub target_user_id: String,
|
||||
|
||||
/// Device ID (or master-key ID) that the signature targets.
|
||||
#[pyo3(get)]
|
||||
pub target_device_id: String,
|
||||
|
||||
/// Raw signature value.
|
||||
#[pyo3(get)]
|
||||
pub signature: Py<PyAny>,
|
||||
}
|
||||
|
||||
#[pymethods]
|
||||
impl SignatureListItem {
|
||||
#[new]
|
||||
fn py_new(
|
||||
signing_key_id: String,
|
||||
target_user_id: String,
|
||||
target_device_id: String,
|
||||
signature: Py<PyAny>,
|
||||
) -> Self {
|
||||
Self {
|
||||
signing_key_id,
|
||||
target_user_id,
|
||||
target_device_id,
|
||||
signature,
|
||||
}
|
||||
}
|
||||
|
||||
fn __repr__(&self) -> String {
|
||||
format!(
|
||||
"SignatureListItem(signing_key_id={:?}, target_user_id={:?}, target_device_id={:?})",
|
||||
self.signing_key_id, self.target_user_id, self.target_device_id,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ use pyo3_log::ResetHandle;
|
||||
pub mod acl;
|
||||
pub mod canonical_json;
|
||||
pub mod duration;
|
||||
pub mod e2e_keys;
|
||||
pub mod errors;
|
||||
pub mod events;
|
||||
pub mod http;
|
||||
@@ -64,6 +65,7 @@ fn synapse_rust(py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
|
||||
|
||||
acl::register_module(py, m)?;
|
||||
push::register_module(py, m)?;
|
||||
e2e_keys::register_module(py, m)?;
|
||||
events::register_module(py, m)?;
|
||||
http_client::register_module(py, m)?;
|
||||
rendezvous::register_module(py, m)?;
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, Iterable, Mapping
|
||||
|
||||
import attr
|
||||
from canonicaljson import encode_canonical_json
|
||||
from signedjson.key import VerifyKey, decode_verify_key_bytes
|
||||
from signedjson.sign import SignatureVerifyException, verify_signed_json
|
||||
@@ -35,6 +34,7 @@ from synapse.api.errors import CodeMessageException, Codes, NotFoundError, Synap
|
||||
from synapse.handlers.device import DeviceWriterHandler
|
||||
from synapse.logging.context import make_deferred_yieldable, run_in_background
|
||||
from synapse.logging.opentracing import log_kv, set_tag, tag_args, trace
|
||||
from synapse.synapse_rust.e2e_keys import SignatureListItem
|
||||
from synapse.types import (
|
||||
JsonDict,
|
||||
JsonMapping,
|
||||
@@ -1132,7 +1132,7 @@ class E2eKeysHandler:
|
||||
|
||||
async def _process_self_signatures(
|
||||
self, user_id: str, signatures: JsonDict
|
||||
) -> tuple[list["SignatureListItem"], dict[str, dict[str, dict]]]:
|
||||
) -> tuple[list[SignatureListItem], dict[str, dict[str, dict]]]:
|
||||
"""Process uploaded signatures of the user's own keys.
|
||||
|
||||
Signatures of the user's own keys from this API come in two forms:
|
||||
@@ -1150,7 +1150,7 @@ class E2eKeysHandler:
|
||||
Raises:
|
||||
SynapseError: if the input is malformed
|
||||
"""
|
||||
signature_list: list["SignatureListItem"] = []
|
||||
signature_list: list[SignatureListItem] = []
|
||||
failures: dict[str, dict[str, JsonDict]] = {}
|
||||
if not signatures:
|
||||
return signature_list, failures
|
||||
@@ -1252,7 +1252,7 @@ class E2eKeysHandler:
|
||||
signed_master_key: JsonDict,
|
||||
stored_master_key: JsonMapping,
|
||||
devices: dict[str, dict[str, JsonDict]],
|
||||
) -> list["SignatureListItem"]:
|
||||
) -> list[SignatureListItem]:
|
||||
"""Check signatures of a user's master key made by their devices.
|
||||
|
||||
Args:
|
||||
@@ -1296,7 +1296,7 @@ class E2eKeysHandler:
|
||||
|
||||
async def _process_other_signatures(
|
||||
self, user_id: str, signatures: dict[str, dict]
|
||||
) -> tuple[list["SignatureListItem"], dict[str, dict[str, dict]]]:
|
||||
) -> tuple[list[SignatureListItem], dict[str, dict[str, dict]]]:
|
||||
"""Process uploaded signatures of other users' keys. These will be the
|
||||
target user's master keys, signed by the uploading user's user-signing
|
||||
key.
|
||||
@@ -1312,7 +1312,7 @@ class E2eKeysHandler:
|
||||
Raises:
|
||||
SynapseError: if the input is malformed
|
||||
"""
|
||||
signature_list: list["SignatureListItem"] = []
|
||||
signature_list: list[SignatureListItem] = []
|
||||
failures: dict[str, dict[str, JsonDict]] = {}
|
||||
if not signatures:
|
||||
return signature_list, failures
|
||||
@@ -1747,16 +1747,6 @@ def _one_time_keys_match(old_key_json: str, new_key: JsonDict) -> bool:
|
||||
return old_key == new_key_copy
|
||||
|
||||
|
||||
@attr.s(slots=True, auto_attribs=True)
|
||||
class SignatureListItem:
|
||||
"""An item in the signature list as used by upload_signatures_for_device_keys."""
|
||||
|
||||
signing_key_id: str
|
||||
target_user_id: str
|
||||
target_device_id: str
|
||||
signature: JsonDict
|
||||
|
||||
|
||||
class SigningKeyEduUpdater:
|
||||
"""Handles incoming signing key updates from federation and updates the DB"""
|
||||
|
||||
|
||||
@@ -61,8 +61,8 @@ from synapse.util.iterutils import batch_iter
|
||||
from synapse.util.json import json_decoder, json_encoder
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from synapse.handlers.e2e_keys import SignatureListItem
|
||||
from synapse.server import HomeServer
|
||||
from synapse.synapse_rust.e2e_keys import SignatureListItem
|
||||
|
||||
|
||||
@attr.s(slots=True, auto_attribs=True)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
from typing import Any
|
||||
|
||||
class SignatureListItem:
|
||||
"""A pending cross-signing signature."""
|
||||
|
||||
signing_key_id: str
|
||||
""" Full key ID of the signing key, e.g. `"ed25519:ABCDEF"`."""
|
||||
|
||||
target_user_id: str
|
||||
"""User whose key was signed."""
|
||||
|
||||
target_device_id: str
|
||||
"""Device ID (or master-key ID) that the signature targets."""
|
||||
|
||||
signature: Any
|
||||
"""Raw signature value."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
signing_key_id: str,
|
||||
target_user_id: str,
|
||||
target_device_id: str,
|
||||
signature: Any,
|
||||
) -> None: ...
|
||||
Reference in New Issue
Block a user