Skip to content
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

Keyrings, fetchers and databases #216

Open
neilalexander opened this issue Aug 27, 2020 · 1 comment
Open

Keyrings, fetchers and databases #216

neilalexander opened this issue Aug 27, 2020 · 1 comment
Labels

Comments

@neilalexander
Copy link
Contributor

The shape around this is a bit weird. We might want to rethink it at some point.

@neilalexander neilalexander added the distant future We'll look at this, at some point in the future, maybe label Aug 27, 2020
@kegsay kegsay added T-Task and removed distant future We'll look at this, at some point in the future, maybe labels Dec 6, 2022
@kegsay
Copy link
Member

kegsay commented Apr 19, 2023

This has since been expanded in light of some portable accounts work, which require other keys to self-sign event JSON. The current model has:

  • KeyFetcher - interface which takes server name, key ID and valid at timestamps and spits out the key, expired + valid until timestamps
  • KeyDatabase - interface with all of KeyFetcher with a new StoreKeys function which can store the output of the above function.
  • KeyRing - struct with a list of key fetchers and a single key database. The KeyRing is the concrete impl which implements JSONVerifier but also manages the entire control flow of fetching from DB, verifying, working out what's left and hitting the key fetchers, then storing the results. In other words, it does too much.
  • KeyClient - interface over FederationClient to get server keys for the destination and lookup server keys e.g notary/perspective.
  • PerspectiveKeyFetcher and DirectKeyFetcher - do as they say, they implement KeyFetcher.

All parts of the model:

  • share concrete federation structs which have JSON tags
  • heavily assume JSON (down to storing raw bytes)

This is brittle because:

  • It makes it harder to use data formats other than JSON.
  • It makes it harder for the federation API to change without breaking GMSL (if we remove a key in the HTTP API, we need to change most of GMSL's key bits).

Dendrite leans on this model heavily to pull out keys and then use them to verify events. It doesn't actually dig deep into the model though. The only bit it actually seems to care about are ServerKeys which it then signs when acting as a notary server.

Proposal

  • Remove KeyDatabase entirely, and expect the caller to handle key caching. This will simplify KeyRing and make it clearer when things are being cached vs making costly network calls.
  • Make an abstraction between the federation HTTP response format and what we deal with in GMSL. We need to keep some of the response format for verifying signatures only. After that, we should just be dealing with the 3-uple (server, key ID, pub key). Said abstraction can both hide the fact we're dealing with JSON and making fed API calls. E.g:
type Key interface {
	// Verify that the key was signed by the given tuple of name + key ID.
	Verify(signingName string, keyID spec.KeyID) error
	// The key in question.
	Value() crypto.PublicKey
}

This allows DBs to cache in a more optimised manner as well, as they aren't forced to marshal/unmarshal JSON.

The main way these keys are obtained are via:

  • Directly asking the server (signing name).
  • Asking for a specific event (signing name, key ID and valid at TS).

This can be interfaced up and concrete impls like pseudo IDs can just ignore the valid at TS (as it's always valid).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants