-
-
Notifications
You must be signed in to change notification settings - Fork 146
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Verify only the required signatures on verify_event
#394
Conversation
The spec says that the required signatures for a signed event is the signature of sender's server (unless is a third party invite) and the `event_id` server (in v1 and v2 room versions). This changes the previous behaviour, which tried to verify the signatures for all the servers in the `PublicKeyMap`, instead of checking only the required signatures. Relevant spec section: https://matrix.org/docs/spec/server_server/r0.1.4#validating-hashes-and-signatures-on-received-events
/// assert!(verify_event(&public_key_map, &object, &RoomVersionId::Version6).is_ok()); | ||
/// let verification_result = verify_event(&public_key_map, &object, &RoomVersionId::Version6); | ||
/// assert!(verification_result.is_ok()); | ||
/// assert!(matches!(verification_result.unwrap(), Verified::All)); | ||
/// ``` | ||
pub fn verify_event( | ||
public_key_map: &PublicKeyMap, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PublicKeyMap
forces to load all the known server keys before calling to this function. I was thinking about adding a trait to be able to provide multiple implementations and, for example, be able to provide an implementation which loads the keys on demand.
What do you think about it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the kind of situation where you would use a Stream
, but I'm not sure. Whatever you think works best.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, as it is right now, PublicKeyMap
should contain all the public keys for all known servers. What I was thinking on was to have an alternative implementation which lazy loads the public keys on demand (Stream
does not solve this problem, as far as I know). If I add the trait, I would do it on another PR.
Thanks anyway for the suggestion!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does Stream
not solve this? A stream is basically just an asynchronous (which is just a guess that it'd be useful for homeservers) iterator, and iterators only do work when iterated. When you stop iteration (or polling in the case of a stream) early, any logic that's part of the iterator / stream itself is not invoked again to produce the remaining elements. Of course it somewhat depends on how the stream is constructed whether this decreases work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that I probably missed in giving enough context. What the verify_event
needs is random access to one or two keys on the PublicKeyMap
( for example, it will need to look up the server keys for matrix.org
if it needs to authorize an event sent from a user on matrix.org
). The function does not need to iterate over all the known server keys.
The Stream
approach could work if the signing keys were selected before hand (for example, select matrix.org
and anotherserver.com
) and then use this stream as an input for this function. The unique problem I see with this approach is that it could potentially be misused by, for example, give an empty Stream
and do not verify any signature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes a lot of sense! So your idea was to provide a generic argument that the function can then ask for the keys to a certain homeserver through a trait? Sounds like a good idea!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder whether it actually needs a new trait. Could it just be a FnMut(&ServerName) -> PublicKeySet
/ FnMut(&str) -> PublicKeySet
or sth. along those lines?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that could work as well! I thought on adding a trait just for the semantics.
I do not know if it makes any difference on compilation times 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure how helpful this is but here is the code for dealing with this so far in conduit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR, especially for including a changelog entry, documentation improvements and tests!
I'm not super keen on owning / maintaining ruma-signatures so haven't tried to understand the main logic change. If you want that double-checked you will have to find sbd. else to review it.
Feel free to merge this PR yourself whenever you think it's ready.
/// assert!(verify_event(&public_key_map, &object, &RoomVersionId::Version6).is_ok()); | ||
/// let verification_result = verify_event(&public_key_map, &object, &RoomVersionId::Version6); | ||
/// assert!(verification_result.is_ok()); | ||
/// assert!(matches!(verification_result.unwrap(), Verified::All)); | ||
/// ``` | ||
pub fn verify_event( | ||
public_key_map: &PublicKeyMap, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, as it is right now, PublicKeyMap
should contain all the public keys for all known servers. What I was thinking on was to have an alternative implementation which lazy loads the public keys on demand (Stream
does not solve this problem, as far as I know). If I add the trait, I would do it on another PR.
Thanks anyway for the suggestion!
@DevinR528 I see that the latest changes on
@jplatte I'm not authorized to do that 😅 |
I've made a few adjustments, are you still getting an authorization error? |
It seems that I see the merge button now. Thanks! |
Everything looks good to me too! I don't see any reason why this wouldn't work the same as before but more streamlined. If you want to make double sure I can test it out in conduit tomorrow but I think it should be fine. |
There's a subtle but important change compared to the previous version: Before it was checking that all keys provided on The new code only requires to check the signature for sender's homeserver. For example, imagine an event like:
This event would be accepted by the previous version (signature for @DevinR528 If you don't have any new concern after this clarification, I will go ahead and merge this PR. Thanks for reviewing it, anyway! |
Yeah, go for it! So this means that I shouldn't be using the |
I don't think I know the answer to your question, but: I guess that in almost all cases Maybe this is one of those cases in which |
The spec says that the required signatures for a signed event is the
signature of sender's server (unless is a third party invite) and the
event_id
server (in v1 and v2 room versions).This changes the previous behaviour, which tried to verify the
signatures for all the servers in the
PublicKeyMap
, instead ofchecking only the required signatures.
Relevant spec section:
https://matrix.org/docs/spec/server_server/r0.1.4#validating-hashes-and-signatures-on-received-events