Allow specifying old signing keys with the public key and key ID only

This commit is contained in:
Neil Alexander 2022-10-06 11:08:49 +01:00
parent 3f82bceb70
commit fd8bc16d10
No known key found for this signature in database
GPG key ID: A02A2019A2BB0944
5 changed files with 49 additions and 20 deletions

View file

@ -18,12 +18,17 @@ global:
private_key: matrix_key.pem private_key: matrix_key.pem
# The paths and expiry timestamps (as a UNIX timestamp in millisecond precision) # The paths and expiry timestamps (as a UNIX timestamp in millisecond precision)
# to old signing private keys that were formerly in use on this domain. These # to old signing keys that were formerly in use on this domain name. These
# keys will not be used for federation request or event signing, but will be # keys will not be used for federation request or event signing, but will be
# provided to any other homeserver that asks when trying to verify old events. # provided to any other homeserver that asks when trying to verify old events.
old_private_keys: old_private_keys:
# If the old private key file is available:
# - private_key: old_matrix_key.pem # - private_key: old_matrix_key.pem
# expired_at: 1601024554498 # expired_at: 1601024554498
# If only the public key and key ID is known:
# - public_key: mn59Kxfdq9VziYHSBzI7+EDPDcBS2Xl7jeUdiiQcOnM=
# key_id: ed25519:mykeyid
# expired_at: 1601024554498
# How long a remote server can cache our server signing key before requesting it # How long a remote server can cache our server signing key before requesting it
# again. Increasing this number will reduce the number of requests made by other # again. Increasing this number will reduce the number of requests made by other

View file

@ -18,12 +18,17 @@ global:
private_key: matrix_key.pem private_key: matrix_key.pem
# The paths and expiry timestamps (as a UNIX timestamp in millisecond precision) # The paths and expiry timestamps (as a UNIX timestamp in millisecond precision)
# to old signing private keys that were formerly in use on this domain. These # to old signing keys that were formerly in use on this domain name. These
# keys will not be used for federation request or event signing, but will be # keys will not be used for federation request or event signing, but will be
# provided to any other homeserver that asks when trying to verify old events. # provided to any other homeserver that asks when trying to verify old events.
old_private_keys: old_private_keys:
# If the old private key file is available:
# - private_key: old_matrix_key.pem # - private_key: old_matrix_key.pem
# expired_at: 1601024554498 # expired_at: 1601024554498
# If only the public key and key ID is known:
# - public_key: mn59Kxfdq9VziYHSBzI7+EDPDcBS2Xl7jeUdiiQcOnM=
# key_id: ed25519:mykeyid
# expired_at: 1601024554498
# How long a remote server can cache our server signing key before requesting it # How long a remote server can cache our server signing key before requesting it
# again. Increasing this number will reduce the number of requests made by other # again. Increasing this number will reduce the number of requests made by other

View file

@ -160,7 +160,7 @@ func localKeys(cfg *config.FederationAPI, validUntil time.Time) (*gomatrixserver
for _, oldVerifyKey := range cfg.Matrix.OldVerifyKeys { for _, oldVerifyKey := range cfg.Matrix.OldVerifyKeys {
keys.OldVerifyKeys[oldVerifyKey.KeyID] = gomatrixserverlib.OldVerifyKey{ keys.OldVerifyKeys[oldVerifyKey.KeyID] = gomatrixserverlib.OldVerifyKey{
VerifyKey: gomatrixserverlib.VerifyKey{ VerifyKey: gomatrixserverlib.VerifyKey{
Key: gomatrixserverlib.Base64Bytes(oldVerifyKey.PrivateKey.Public().(ed25519.PublicKey)), Key: gomatrixserverlib.Base64Bytes(oldVerifyKey.PublicKey),
}, },
ExpiredTS: oldVerifyKey.ExpiredAt, ExpiredTS: oldVerifyKey.ExpiredAt,
} }

View file

@ -231,24 +231,40 @@ func loadConfig(
return nil, err return nil, err
} }
for i, oldPrivateKey := range c.Global.OldVerifyKeys { for _, key := range c.Global.OldVerifyKeys {
var oldPrivateKeyData []byte switch {
case key.KeyID == "":
return nil, fmt.Errorf("key ID must be specified for old_verify_keys")
oldPrivateKeyPath := absPath(basePath, oldPrivateKey.PrivateKeyPath) case len(key.PublicKey) == ed25519.PublicKeySize:
oldPrivateKeyData, err = readFile(oldPrivateKeyPath) continue
if err != nil {
return nil, err case len(key.PublicKey) > 0:
return nil, fmt.Errorf("the public_key is the wrong length")
case key.PrivateKeyPath == "":
return nil, fmt.Errorf("a private_key path must be specified if public_key isn't")
default:
var oldPrivateKeyData []byte
oldPrivateKeyPath := absPath(basePath, key.PrivateKeyPath)
oldPrivateKeyData, err = readFile(oldPrivateKeyPath)
if err != nil {
return nil, fmt.Errorf("failed to read %q: %w", oldPrivateKeyPath, err)
}
// NOTSPEC: Ordinarily we should enforce key ID formatting, but since there are
// a number of private keys out there with non-compatible symbols in them due
// to lack of validation in Synapse, we won't enforce that for old verify keys.
keyID, privateKey, perr := readKeyPEM(oldPrivateKeyPath, oldPrivateKeyData, false)
if perr != nil {
return nil, fmt.Errorf("failed to parse %q: %w", oldPrivateKeyPath, perr)
}
key.KeyID = keyID
key.PrivateKey = privateKey
key.PublicKey = privateKey.Public().(ed25519.PublicKey)
} }
// NOTSPEC: Ordinarily we should enforce key ID formatting, but since there are
// a number of private keys out there with non-compatible symbols in them due
// to lack of validation in Synapse, we won't enforce that for old verify keys.
keyID, privateKey, perr := readKeyPEM(oldPrivateKeyPath, oldPrivateKeyData, false)
if perr != nil {
return nil, perr
}
c.Global.OldVerifyKeys[i].KeyID, c.Global.OldVerifyKeys[i].PrivateKey = keyID, privateKey
} }
c.MediaAPI.AbsBasePath = Path(absPath(basePath, c.MediaAPI.BasePath)) c.MediaAPI.AbsBasePath = Path(absPath(basePath, c.MediaAPI.BasePath))

View file

@ -27,7 +27,7 @@ type Global struct {
// Information about old private keys that used to be used to sign requests and // 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 // 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. // servers that ask for them to help verify old events.
OldVerifyKeys []OldVerifyKeys `yaml:"old_private_keys"` OldVerifyKeys []*OldVerifyKeys `yaml:"old_private_keys"`
// How long a remote server can cache our server key for before requesting it again. // 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 // Increasing this number will reduce the number of requests made by remote servers
@ -127,6 +127,9 @@ type OldVerifyKeys struct {
// The private key itself. // The private key itself.
PrivateKey ed25519.PrivateKey `yaml:"-"` PrivateKey ed25519.PrivateKey `yaml:"-"`
// The public key, in case only that part is known.
PublicKey ed25519.PublicKey `yaml:"public_key"`
// The key ID of the private key. // The key ID of the private key.
KeyID gomatrixserverlib.KeyID `yaml:"-"` KeyID gomatrixserverlib.KeyID `yaml:"-"`