|
|
- import logging
- from urllib.parse import urljoin
- from uuid import uuid4
-
- import requests
-
- from .appdata import AppData
- from .jwe_handler import JWEHandler
- from .utils import sha256_base64, RequestFailure
-
- logger = logging.getLogger(__name__)
-
-
- class XKey:
- REGISTRY_URL = ("https://appregistry-posteid.mobile.poste.it"
- "/jod-app-registry/")
- APP_NAME = "app-posteid-v3"
- ACTIVITY_ID = "C6050AC80E8B5288A01237"
- DEVICE_SPECS = ("Android", "11",
- "sdk_gphone_x86_64_arm64", "4.5.204",
- "true")
-
- def __init__(self, profile_name):
- self.appdata = AppData(profile_name)
- self.s = requests.Session()
- self.s.headers = {'Accept-Encoding': "gzip",
- 'User-Agent': "okhttp/3.12.1",
- 'Connection': "keep-alive"}
- self.jwe_handler = JWEHandler(self.appdata)
-
- def _send_req(self, request):
- prepped = self.s.prepare_request(request)
- return self.s.send(prepped)
-
- def _register_stage_init(self, register_nonce):
- url = urljoin(self.REGISTRY_URL, "v2/registerInit")
- headers = {'Content-Type': "application/json; charset=UTF-8"}
- data = {}
- data['appName'] = "app-posteid-v3"
- data['initCodeChallenge'] = sha256_base64(register_nonce)
- logger.debug(f"Registration(INIT): sending challenge: {data}")
- ans = self.s.post(url, headers=headers, json=data)
- if ans.status_code != 200:
- raise RequestFailure(f"Wrong status code: {ans.status_code}", ans)
- if not ans.headers.get('Content-Type').startswith("application/json"):
- raise RequestFailure("Response not JSON.", ans)
- ans_json = ans.json()
- if 'pubServerKey' not in ans_json:
- raise RequetFailure("Response does not contain 'pubServerKey'",
- ans)
- pubkey = ans_json['pubServerKey']
- self.appdata.serv_pubkey = pubkey
- logger.debug(f"Registration(INIT): got server pubkey: {pubkey}.")
-
- def _register_stage_register(self, register_nonce):
- url = urljoin(self.REGISTRY_URL, "v2/register")
- data = {}
- data['initCodeVerifier'] = register_nonce
- data['xdevice'] = self.ACTIVITY_ID + "::" + ":".join(self.DEVICE_SPECS)
- data['pubAppKey'] = self.appdata.app_privkey.pubkey_b64
- logger.debug("Registration(REG): encrypting app data.")
- jwe_req = self.jwe_handler.req_jwe_post(url, "register", data)
- logger.debug("Registration(REG): sending app data.")
- ans = self._send_req(jwe_req)
- if ans.status_code != 200:
- raise RequestFailure(f"Wrong status code: {ans.status_code}", ans)
- logger.debug("Registration(REG): decrypting response.")
- ans_json = self.jwe_handler.decrypt(ans.content)
- logger.debug(f"Registration(REG): decrypted response: {ans_json}")
- if 'data' not in ans_json:
- raise RequestFailure("Malformed request, missing 'data'.", ans)
- if 'app-uuid' not in ans_json['data']:
- raise RequestFailure("Malformed request, missing 'app-uuid'.", ans)
- if 'otpSecretKey' not in ans_json['data']:
- raise RequestFailure("Malformed request, missing 'otpSecretKey'.",
- ans)
- self.appdata['xkey_appuuid'] = ans_json['data']['app-uuid']
- self.appdata['xkey_seed'] = ans_json['data']['otpSecretKey']
-
- def _register_stage_activate(self):
- url = urljoin(self.REGISTRY_URL, "v2/activation")
- logger.debug("Registration(ACTIVATE): encrypting request.")
- jwe_req = self.jwe_handler.req_jwe_post(url, "activation", {},
- auth=True)
- logger.debug("Registration(ACTIVATE): sending request.")
- ans = self._send_req(jwe_req)
- if ans.status_code != 200:
- raise RequestFailure(f"Wrong status code: {ans.status_code}", ans)
- self.appdata['activated'] = True
- logger.debug("Registration(ACTIVATE): activated.")
-
- def _register_stage_update(self, register_nonce):
- url = urljoin(self.REGISTRY_URL, "v2/register")
- data = {}
- data['initCodeVerifier'] = register_nonce
- data['xdevice'] = self.ACTIVITY_ID + "::" + ":".join(self.DEVICE_SPECS)
- data['pubAppKey'] = self.appdata.app_privkey.pubkey_b64
- logger.debug("Registration(UPDATE): encrypting app data.")
- jwe_req = self.jwe_handler.req_jwe_post(url, "registerUpdate", data,
- auth=True)
- logger.debug("Registration(UPDATE): sending app data.")
- ans = self._send_req(jwe_req)
- if ans.status_code != 200:
- raise RequestFailure(f"Wrong status code: {ans.status_code}", ans)
- logger.debug("Registration(UPDATE): decrypting response.")
- ans_json = self.jwe_handler.decrypt(ans.content)
- logger.debug(f"Registration(UPDATE): decrypted response: {ans_json}")
- if 'data' not in ans_json:
- raise RequestFailure("Malformed request, missing 'data'.", ans)
- if 'app-uuid' not in ans_json['data']:
- raise RequestFailure("Malformed request, missing 'app-uuid'.", ans)
- if 'otpSecretKey' not in ans_json['data']:
- raise RequestFailure("Malformed request, missing 'otpSecretKey'.",
- ans)
- self.appdata['xkey_appuuid'] = ans_json['data']['app-uuid']
- self.appdata['xkey_seed'] = ans_json['data']['otpSecretKey']
-
- def register_xkey(self):
- register_nonce = str(uuid4())
- logger.debug(f"Starting registration (nonce: {register_nonce}).")
- self._register_stage_init(register_nonce)
- if self.appdata['xkey_seed']:
- self._register_stage_update(register_nonce)
- else:
- self._register_stage_register(register_nonce)
- self._register_stage_activate()
|