diff --git a/synapse/config/key.py b/synapse/config/key.py
index a2de6d5c17..0494c0cb77 100644
--- a/synapse/config/key.py
+++ b/synapse/config/key.py
@@ -20,48 +20,58 @@ from syutil.crypto.signing_key import (
is_signing_algorithm_supported, decode_verify_key_bytes
)
from syutil.base64util import decode_base64
+from synapse.util.stringutils import random_string
class KeyConfig(Config):
- def __init__(self, args):
- super(KeyConfig, self).__init__(args)
- self.signing_key = self.read_signing_key(args.signing_key_path)
+ def read_config(self, config):
+ self.signing_key = self.read_signing_key(config["signing_key_path"])
self.old_signing_keys = self.read_old_signing_keys(
- args.old_signing_key_path
+ config["old_signing_keys"]
+ )
+ self.key_refresh_interval = self.parse_duration(
+ config["key_refresh_interval"]
)
- self.key_refresh_interval = args.key_refresh_interval
self.perspectives = self.read_perspectives(
- args.perspectives_config_path
+ config["perspectives"]
)
- @classmethod
- def add_arguments(cls, parser):
- super(KeyConfig, cls).add_arguments(parser)
- key_group = parser.add_argument_group("keys")
- key_group.add_argument("--signing-key-path",
- help="The signing key to sign messages with")
- key_group.add_argument("--old-signing-key-path",
- help="The keys that the server used to sign"
- " sign messages with but won't use"
- " to sign new messages. E.g. it has"
- " lost its private key")
- key_group.add_argument("--key-refresh-interval",
- default=24 * 60 * 60 * 1000, # 1 Day
- help="How long a key response is valid for."
- " Used to set the exipiry in /key/v2/."
- " Controls how frequently servers will"
- " query what keys are still valid")
- key_group.add_argument("--perspectives-config-path",
- help="The trusted servers to download signing"
- " keys from")
-
- def read_perspectives(self, perspectives_config_path):
- config = self.read_yaml_file(
- perspectives_config_path, "perspectives_config_path"
- )
+ def default_config(self, config_dir_path, server_name):
+ base_key_name = os.path.join(config_dir_path, server_name)
+ return """\
+ ## Signing Keys ##
+
+ # Path to the signing key to sign messages with
+ signing_key_path: "%(base_key_name)s.signing.key"
+
+ # The keys that the server used to sign messages with but won't use
+ # to sign new messages. E.g. it has lost its private key
+ old_signing_keys: {}
+ # "ed25519:auto":
+ # # Base64 encoded public key
+ # key: "The public part of your old signing key."
+ # # Millisecond POSIX timestamp when the key expired.
+ # expired_ts: 123456789123
+
+ # How long key response published by this server is valid for.
+ # Used to set the valid_until_ts in /key/v2 APIs.
+ # Determines how quickly servers will query to check which keys
+ # are still valid.
+ key_refresh_interval: "1d" # 1 Day.
+
+ # The trusted servers to download signing keys from.
+ perspectives:
+ servers:
+ "matrix.org":
+ verify_keys:
+ "ed25519:auto":
+ key: "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw"
+ """ % locals()
+
+ def read_perspectives(self, perspectives_config):
servers = {}
- for server_name, server_config in config["servers"].items():
+ for server_name, server_config in perspectives_config["servers"].items():
for key_id, key_data in server_config["verify_keys"].items():
if is_signing_algorithm_supported(key_id):
key_base64 = key_data["key"]
@@ -82,66 +92,42 @@ class KeyConfig(Config):
" Try running again with --generate-config"
)
- def read_old_signing_keys(self, old_signing_key_path):
- old_signing_keys = self.read_file(
- old_signing_key_path, "old_signing_key"
- )
- try:
- return syutil.crypto.signing_key.read_old_signing_keys(
- old_signing_keys.splitlines(True)
- )
- except Exception:
- raise ConfigError(
- "Error reading old signing keys."
- )
-
- @classmethod
- def generate_config(cls, args, config_dir_path):
- super(KeyConfig, cls).generate_config(args, config_dir_path)
- base_key_name = os.path.join(config_dir_path, args.server_name)
-
- args.pid_file = os.path.abspath(args.pid_file)
-
- if not args.signing_key_path:
- args.signing_key_path = base_key_name + ".signing.key"
+ def read_old_signing_keys(self, old_signing_keys):
+ keys = {}
+ for key_id, key_data in old_signing_keys.items():
+ if is_signing_algorithm_supported(key_id):
+ key_base64 = key_data["key"]
+ key_bytes = decode_base64(key_base64)
+ verify_key = decode_verify_key_bytes(key_id, key_bytes)
+ verify_key.expired_ts = key_data["expired_ts"]
+ keys[key_id] = verify_key
+ else:
+ raise ConfigError(
+ "Unsupported signing algorithm for old key: %r" % (key_id,)
+ )
+ return keys
- if not os.path.exists(args.signing_key_path):
- with open(args.signing_key_path, "w") as signing_key_file:
+ def generate_files(self, config):
+ signing_key_path = config["signing_key_path"]
+ if not os.path.exists(signing_key_path):
+ with open(signing_key_path, "w") as signing_key_file:
+ key_id = "a_" + random_string(4)
syutil.crypto.signing_key.write_signing_keys(
signing_key_file,
- (syutil.crypto.signing_key.generate_signing_key("auto"),),
+ (syutil.crypto.signing_key.generate_signing_key(key_id),),
)
else:
- signing_keys = cls.read_file(args.signing_key_path, "signing_key")
+ signing_keys = self.read_file(signing_key_path, "signing_key")
if len(signing_keys.split("\n")[0].split()) == 1:
# handle keys in the old format.
+ key_id = "a_" + random_string(4)
key = syutil.crypto.signing_key.decode_signing_key_base64(
syutil.crypto.signing_key.NACL_ED25519,
- "auto",
+ key_id,
signing_keys.split("\n")[0]
)
- with open(args.signing_key_path, "w") as signing_key_file:
+ with open(signing_key_path, "w") as signing_key_file:
syutil.crypto.signing_key.write_signing_keys(
signing_key_file,
(key,),
)
-
- if not args.old_signing_key_path:
- args.old_signing_key_path = base_key_name + ".old.signing.keys"
-
- if not os.path.exists(args.old_signing_key_path):
- with open(args.old_signing_key_path, "w"):
- pass
-
- if not args.perspectives_config_path:
- args.perspectives_config_path = base_key_name + ".perspectives"
-
- if not os.path.exists(args.perspectives_config_path):
- with open(args.perspectives_config_path, "w") as perspectives_file:
- perspectives_file.write(
- 'servers:\n'
- ' matrix.org:\n'
- ' verify_keys:\n'
- ' "ed25519:auto":\n'
- ' key: "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw"\n'
- )
|