ruma_signatures/
verification.rs

1//! Verification of digital signatures.
2
3use ed25519_dalek::{Verifier as _, VerifyingKey};
4use ruma_common::SigningKeyAlgorithm;
5
6use crate::{Error, ParseError, VerificationError};
7
8/// A digital signature verifier.
9pub(crate) trait Verifier {
10    /// Use a public key to verify a signature against the JSON object that was signed.
11    ///
12    /// # Parameters
13    ///
14    /// * `public_key`: The raw bytes of the public key of the key pair used to sign the message.
15    /// * `signature`: The raw bytes of the signature to verify.
16    /// * `message`: The raw bytes of the message that was signed.
17    ///
18    /// # Errors
19    ///
20    /// Returns an error if verification fails.
21    fn verify_json(&self, public_key: &[u8], signature: &[u8], message: &[u8])
22        -> Result<(), Error>;
23}
24
25/// A verifier for Ed25519 digital signatures.
26#[derive(Debug, Default)]
27pub(crate) struct Ed25519Verifier;
28
29impl Verifier for Ed25519Verifier {
30    fn verify_json(
31        &self,
32        public_key: &[u8],
33        signature: &[u8],
34        message: &[u8],
35    ) -> Result<(), Error> {
36        VerifyingKey::from_bytes(
37            public_key
38                .try_into()
39                .map_err(|_| ParseError::PublicKey(ed25519_dalek::SignatureError::new()))?,
40        )
41        .map_err(ParseError::PublicKey)?
42        .verify(message, &signature.try_into().map_err(ParseError::Signature)?)
43        .map_err(VerificationError::Signature)
44        .map_err(Error::from)
45    }
46}
47
48/// A value returned when an event is successfully verified.
49///
50/// Event verification involves verifying both signatures and a content hash. It is possible for
51/// the signatures on an event to be valid, but for the hash to be different than the one
52/// calculated during verification. This is not necessarily an error condition, as it may indicate
53/// that the event has been redacted. In this case, receiving homeservers should store a redacted
54/// version of the event.
55#[derive(Clone, Debug, Hash, PartialEq, Eq)]
56#[allow(clippy::exhaustive_enums)]
57pub enum Verified {
58    /// All signatures are valid and the content hashes match.
59    All,
60
61    /// All signatures are valid but the content hashes don't match.
62    ///
63    /// This may indicate a redacted event.
64    Signatures,
65}
66
67/// Get the verifier for the given algorithm, if it is supported.
68pub(crate) fn verifier_from_algorithm(algorithm: &SigningKeyAlgorithm) -> Option<impl Verifier> {
69    match algorithm {
70        SigningKeyAlgorithm::Ed25519 => Some(Ed25519Verifier),
71        _ => None,
72    }
73}