Allow specifying old signing keys with the public key and key ID only (#2770)
If the private key file is lost, it's often possible to retrieve the public key from another server elsewhere, so we should make it possible to configure it in that way.
This commit is contained in:
parent
ec5d1d681d
commit
d605d928bc
|
@ -18,12 +18,17 @@ global:
|
|||
private_key: matrix_key.pem
|
||||
|
||||
# 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
|
||||
# provided to any other homeserver that asks when trying to verify old events.
|
||||
old_private_keys:
|
||||
# If the old private key file is available:
|
||||
# - private_key: old_matrix_key.pem
|
||||
# expired_at: 1601024554498
|
||||
# If only the public key (in base64 format) and key ID are 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
|
||||
# again. Increasing this number will reduce the number of requests made by other
|
||||
|
|
|
@ -18,12 +18,17 @@ global:
|
|||
private_key: matrix_key.pem
|
||||
|
||||
# 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
|
||||
# provided to any other homeserver that asks when trying to verify old events.
|
||||
old_private_keys:
|
||||
# If the old private key file is available:
|
||||
# - private_key: old_matrix_key.pem
|
||||
# expired_at: 1601024554498
|
||||
# If only the public key (in base64 format) and key ID are 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
|
||||
# again. Increasing this number will reduce the number of requests made by other
|
||||
|
|
|
@ -160,7 +160,7 @@ func localKeys(cfg *config.FederationAPI, validUntil time.Time) (*gomatrixserver
|
|||
for _, oldVerifyKey := range cfg.Matrix.OldVerifyKeys {
|
||||
keys.OldVerifyKeys[oldVerifyKey.KeyID] = gomatrixserverlib.OldVerifyKey{
|
||||
VerifyKey: gomatrixserverlib.VerifyKey{
|
||||
Key: gomatrixserverlib.Base64Bytes(oldVerifyKey.PrivateKey.Public().(ed25519.PublicKey)),
|
||||
Key: oldVerifyKey.PublicKey,
|
||||
},
|
||||
ExpiredTS: oldVerifyKey.ExpiredAt,
|
||||
}
|
||||
|
|
|
@ -231,13 +231,14 @@ func loadConfig(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
for i, oldPrivateKey := range c.Global.OldVerifyKeys {
|
||||
for _, key := range c.Global.OldVerifyKeys {
|
||||
switch {
|
||||
case key.PrivateKeyPath != "":
|
||||
var oldPrivateKeyData []byte
|
||||
|
||||
oldPrivateKeyPath := absPath(basePath, oldPrivateKey.PrivateKeyPath)
|
||||
oldPrivateKeyPath := absPath(basePath, key.PrivateKeyPath)
|
||||
oldPrivateKeyData, err = readFile(oldPrivateKeyPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("failed to read %q: %w", oldPrivateKeyPath, err)
|
||||
}
|
||||
|
||||
// NOTSPEC: Ordinarily we should enforce key ID formatting, but since there are
|
||||
|
@ -245,10 +246,25 @@ func loadConfig(
|
|||
// 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
|
||||
return nil, fmt.Errorf("failed to parse %q: %w", oldPrivateKeyPath, perr)
|
||||
}
|
||||
|
||||
c.Global.OldVerifyKeys[i].KeyID, c.Global.OldVerifyKeys[i].PrivateKey = keyID, privateKey
|
||||
key.KeyID = keyID
|
||||
key.PrivateKey = privateKey
|
||||
key.PublicKey = gomatrixserverlib.Base64Bytes(privateKey.Public().(ed25519.PublicKey))
|
||||
|
||||
case key.KeyID == "":
|
||||
return nil, fmt.Errorf("'key_id' must be specified if 'public_key' is specified")
|
||||
|
||||
case len(key.PublicKey) == ed25519.PublicKeySize:
|
||||
continue
|
||||
|
||||
case len(key.PublicKey) > 0:
|
||||
return nil, fmt.Errorf("the supplied 'public_key' is the wrong length")
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("either specify a 'private_key' path or supply both 'public_key' and 'key_id'")
|
||||
}
|
||||
}
|
||||
|
||||
c.MediaAPI.AbsBasePath = Path(absPath(basePath, c.MediaAPI.BasePath))
|
||||
|
|
|
@ -27,7 +27,7 @@ type Global struct {
|
|||
// 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"`
|
||||
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
|
||||
|
@ -127,8 +127,11 @@ type OldVerifyKeys struct {
|
|||
// The private key itself.
|
||||
PrivateKey ed25519.PrivateKey `yaml:"-"`
|
||||
|
||||
// The public key, in case only that part is known.
|
||||
PublicKey gomatrixserverlib.Base64Bytes `yaml:"public_key"`
|
||||
|
||||
// The key ID of the private key.
|
||||
KeyID gomatrixserverlib.KeyID `yaml:"-"`
|
||||
KeyID gomatrixserverlib.KeyID `yaml:"key_id"`
|
||||
|
||||
// When the private key was designed as "expired", as a UNIX timestamp
|
||||
// in millisecond precision.
|
||||
|
|
Loading…
Reference in a new issue