From dd7d54b43ca55ba54d94140d612c450c4a457824 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Fri, 25 Sep 2020 10:01:45 +0100 Subject: [PATCH] Allow configuring old verify keys --- federationapi/routing/keys.go | 12 ++++++++++-- internal/config/config.go | 14 ++++++++++++++ internal/config/config_global.go | 20 ++++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/federationapi/routing/keys.go b/federationapi/routing/keys.go index 785be0903..17762b03e 100644 --- a/federationapi/routing/keys.go +++ b/federationapi/routing/keys.go @@ -136,6 +136,8 @@ func localKeys(cfg *config.FederationAPI, validUntil time.Time) (*gomatrixserver var keys gomatrixserverlib.ServerKeys keys.ServerName = cfg.Matrix.ServerName + keys.TLSFingerprints = cfg.TLSFingerPrints + keys.ValidUntilTS = gomatrixserverlib.AsTimestamp(validUntil) publicKey := cfg.Matrix.PrivateKey.Public().(ed25519.PublicKey) @@ -145,9 +147,15 @@ func localKeys(cfg *config.FederationAPI, validUntil time.Time) (*gomatrixserver }, } - keys.TLSFingerprints = cfg.TLSFingerPrints keys.OldVerifyKeys = map[gomatrixserverlib.KeyID]gomatrixserverlib.OldVerifyKey{} - keys.ValidUntilTS = gomatrixserverlib.AsTimestamp(validUntil) + for _, oldVerifyKey := range cfg.Matrix.OldVerifyKeys { + keys.OldVerifyKeys[oldVerifyKey.KeyID] = gomatrixserverlib.OldVerifyKey{ + VerifyKey: gomatrixserverlib.VerifyKey{ + Key: gomatrixserverlib.Base64Bytes(oldVerifyKey.PrivateKey), + }, + ExpiredTS: oldVerifyKey.ExpiredAt, + } + } toSign, err := json.Marshal(keys.ServerKeyFields) if err != nil { diff --git a/internal/config/config.go b/internal/config/config.go index d75500db5..81935f3fc 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -232,6 +232,20 @@ func loadConfig( return nil, err } + for _, oldPrivateKey := range c.Global.OldVerifyKeys { + var oldPrivateKeyData []byte + + oldPrivateKeyPath := absPath(basePath, oldPrivateKey.PrivateKeyPath) + oldPrivateKeyData, err = readFile(oldPrivateKeyPath) + if err != nil { + return nil, err + } + + if oldPrivateKey.KeyID, oldPrivateKey.PrivateKey, err = readKeyPEM(oldPrivateKeyPath, oldPrivateKeyData); err != nil { + return nil, err + } + } + for _, certPath := range c.FederationAPI.FederationCertificatePaths { absCertPath := absPath(basePath, certPath) var pemData []byte diff --git a/internal/config/config_global.go b/internal/config/config_global.go index 03f522be4..d210a3aca 100644 --- a/internal/config/config_global.go +++ b/internal/config/config_global.go @@ -22,6 +22,11 @@ type Global struct { // prefix "ed25519:". KeyID gomatrixserverlib.KeyID `yaml:"-"` + // Information about old private keys that used to be used to sign requests and + // events on this domain. They will not be used but will be advertised to other + // servers that ask for them to help verify old events. + OldVerifyKeys []OldVerifyKeys `yaml:"old_private_keys"` + // How long a remote server can cache our server key for before requesting it again. // Increasing this number will reduce the number of requests made by remote servers // for our key, but increases the period a compromised key will be considered valid @@ -60,6 +65,21 @@ func (c *Global) Verify(configErrs *ConfigErrors, isMonolith bool) { c.Metrics.Verify(configErrs, isMonolith) } +type OldVerifyKeys struct { + // Path to the private key. + PrivateKeyPath Path `yaml:"private_key"` + + // The private key itself. + PrivateKey ed25519.PrivateKey `yaml:"-"` + + // The key ID of the private key. + KeyID gomatrixserverlib.KeyID `yaml:"-"` + + // When the private key was designed as "expired", as a UNIX timestamp + // in millisecond precision. + ExpiredAt gomatrixserverlib.Timestamp `yaml:"expired_at"` +} + // The configuration to use for Prometheus metrics type Metrics struct { // Whether or not the metrics are enabled