[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.
This commit is contained in:
derrod 2021-10-05 07:34:52 +02:00
parent 82f38d279d
commit 8460fdfd2a
3 changed files with 22 additions and 9 deletions

View file

@ -64,6 +64,7 @@ class LegendaryCLI:
def auth(self, args): def auth(self, args):
if args.auth_delete: if args.auth_delete:
self.core.lgd.invalidate_userdata() self.core.lgd.invalidate_userdata()
logger.info('User data deleted.')
return return
try: try:
@ -78,6 +79,10 @@ class LegendaryCLI:
logger.error('Stored credentials were found but were no longer valid. Continuing with login...') logger.error('Stored credentials were found but were no longer valid. Continuing with login...')
self.core.lgd.invalidate_userdata() 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: if args.import_egs_auth:
# get appdata path on Linux # get appdata path on Linux
if not self.core.egl.appdata_path: 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})') logger.error(f'No EGS login session found, please login manually. (Exception: {e!r})')
exit(1) 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 = '' exchange_token = ''
if not args.auth_code and not args.session_id: if not args.auth_code and not args.session_id:
# unfortunately the captcha stuff makes a complete CLI login flow kinda impossible right now... # unfortunately the captcha stuff makes a complete CLI login flow kinda impossible right now...

View file

@ -148,8 +148,18 @@ class LegendaryCore:
raw_data = b64decode(remember_me_data) raw_data = b64decode(remember_me_data)
# data is encrypted # data is encrypted
if raw_data[0] != '{': if raw_data[0] != '{':
raw_data = decrypt_epic_data(self.egl.data_key, raw_data) for data_key in self.egl.data_keys:
re_data = json.loads(raw_data)[0] 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: if 'Token' not in re_data:
raise ValueError('No login session in config') raise ValueError('No login session in config')
refresh_token = re_data['Token'] refresh_token = re_data['Token']
@ -245,7 +255,9 @@ class LegendaryCore:
if 'egl_config' in version_info: if 'egl_config' in version_info:
self.egs.update_egs_params(version_info['egl_config']) self.egs.update_egs_params(version_info['egl_config'])
self._egl_version = version_info['egl_config'].get('version', self._egl_version) 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'): if game_overrides := version_info.get('game_overrides'):
update_workarounds(game_overrides) update_workarounds(game_overrides)
if sdl_config := game_overrides.get('sdl_config'): if sdl_config := game_overrides.get('sdl_config'):

View file

@ -10,9 +10,9 @@ from legendary.models.egl import EGLManifest
class EPCLFS: class EPCLFS:
# Encryption key for JSON data # Known encryption key(s) for JSON user data
# Data is encrypted using AES-256-ECB mode # Data is encrypted using AES-256-ECB mode
data_key = 'A09C853C9E95409BB94D707EADEFA52E' data_keys = []
def __init__(self): def __init__(self):
if os.name == 'nt': if os.name == 'nt':