From 8460fdfd2a7c420f2f05a8fa6731d712b6b784ca Mon Sep 17 00:00:00 2001 From: derrod Date: Tue, 5 Oct 2021 07:34:52 +0200 Subject: [PATCH] [cli/core/lfs] Add support for trying multiple encryption keys Should Epic change the key used for EGL in the future we want to be backwards-compatible to existing (outdated) EGL installs as well as new ones without having to push out a new release. Also forces updating of version data before attempting the import to get the latest key(s) and adds a log message when auth data is deleted. --- legendary/cli.py | 9 +++++---- legendary/core.py | 18 +++++++++++++++--- legendary/lfs/egl.py | 4 ++-- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/legendary/cli.py b/legendary/cli.py index 6601c08..779f4d2 100644 --- a/legendary/cli.py +++ b/legendary/cli.py @@ -64,6 +64,7 @@ class LegendaryCLI: def auth(self, args): if args.auth_delete: self.core.lgd.invalidate_userdata() + logger.info('User data deleted.') return try: @@ -78,6 +79,10 @@ class LegendaryCLI: logger.error('Stored credentials were found but were no longer valid. Continuing with login...') self.core.lgd.invalidate_userdata() + # Force an update check and notice in case there are API changes + self.core.check_for_updates(force=True) + self.core.force_show_update = True + if args.import_egs_auth: # get appdata path on Linux if not self.core.egl.appdata_path: @@ -128,10 +133,6 @@ class LegendaryCLI: logger.error(f'No EGS login session found, please login manually. (Exception: {e!r})') exit(1) - # Force an update check and notice in case there are API changes - self.core.check_for_updates(force=True) - self.core.force_show_update = True - exchange_token = '' if not args.auth_code and not args.session_id: # unfortunately the captcha stuff makes a complete CLI login flow kinda impossible right now... diff --git a/legendary/core.py b/legendary/core.py index 2852a5e..85b0108 100644 --- a/legendary/core.py +++ b/legendary/core.py @@ -148,8 +148,18 @@ class LegendaryCore: raw_data = b64decode(remember_me_data) # data is encrypted if raw_data[0] != '{': - raw_data = decrypt_epic_data(self.egl.data_key, raw_data) - re_data = json.loads(raw_data)[0] + for data_key in self.egl.data_keys: + try: + decrypted_data = decrypt_epic_data(data_key, raw_data) + re_data = json.loads(decrypted_data)[0] + break + except Exception as e: + self.log.debug(f'Decryption with key {data_key} failed with {e!r}') + else: + raise ValueError('Decryption of EPIC launcher user information failed.') + else: + re_data = json.loads(raw_data)[0] + if 'Token' not in re_data: raise ValueError('No login session in config') refresh_token = re_data['Token'] @@ -245,7 +255,9 @@ class LegendaryCore: if 'egl_config' in version_info: self.egs.update_egs_params(version_info['egl_config']) self._egl_version = version_info['egl_config'].get('version', self._egl_version) - self.egl.data_key = version_info['egl_config'].get('data_key', self.egl.data_key) + for data_key in version_info['egl_config'].get('data_keys', []): + if data_key not in self.egl.data_keys: + self.egl.data_keys.append(data_key) if game_overrides := version_info.get('game_overrides'): update_workarounds(game_overrides) if sdl_config := game_overrides.get('sdl_config'): diff --git a/legendary/lfs/egl.py b/legendary/lfs/egl.py index 78503f8..ea9b736 100644 --- a/legendary/lfs/egl.py +++ b/legendary/lfs/egl.py @@ -10,9 +10,9 @@ from legendary.models.egl import EGLManifest class EPCLFS: - # Encryption key for JSON data + # Known encryption key(s) for JSON user data # Data is encrypted using AES-256-ECB mode - data_key = 'A09C853C9E95409BB94D707EADEFA52E' + data_keys = [] def __init__(self): if os.name == 'nt':