from sanic import Sanic, Blueprint, Request, json, SanicException from sanic.log import logger import json as jsonlib import time import urllib.parse import uuid from utils.crypto import base64_decode, base64_encode, xor from utils.crypto import rsa_decrypt, get_rsa_privkey, rsa_sha1_sign from utils.crypto import aes_cbc_decrypt from sdo.model import SdoUser bp_sif_login = Blueprint("sif_login", url_prefix="login") @bp_sif_login.route("authkey", methods=["POST"]) async def authkey(request: Request): request_data = jsonlib.loads(request.form.get("request_data", "")) # type: ignore dummy_token = base64_decode(request_data["dummy_token"]) client_token = base64_encode(rsa_decrypt(dummy_token, get_rsa_privkey())) server_token = base64_encode(uuid.uuid4().bytes) authorize_token = base64_encode(uuid.uuid4().bytes) logger.debug(f"{client_token=} {server_token=} {authorize_token=}") ctx = Sanic.get_app().ctx if not hasattr(ctx, "auth_json"): ctx.auth_json = {} ctx.auth_json[authorize_token] = { "client_token": client_token, "server_token": server_token, } # nonce = 0 # authorize = (f"consumerKey=lovelive_test&" # f"timeStamp={int(time.time())}&" # f"version=1.1&nonce={nonce}&" # f"requestTimeStamp={int(time.time())}") auth_resp = { "response_data": { "authorize_token": authorize_token, "dummy_token": server_token }, "release_info": {}, "status_code": 200 } x_message_sign = base64_encode( rsa_sha1_sign(jsonlib.dumps(auth_resp).encode(), get_rsa_privkey())) logger.debug(f"{auth_resp=} {x_message_sign=}") return json(auth_resp, headers={ "X-Message-Sign": x_message_sign }) @bp_sif_login.route("login", methods=["POST"]) async def login(request: Request): request_data = jsonlib.loads(request.form.get("request_data", "")) # type: ignore authorize = dict(urllib.parse.parse_qsl(request.headers["authorize"])) logger.debug(f"{request_data=} {authorize=}") authorize_token = authorize["token"] tokens = Sanic.get_app().ctx.auth_json[authorize_token] client_token = base64_decode(tokens["client_token"]) server_token = base64_decode(tokens["server_token"]) aes_key = xor(client_token, server_token)[:16] encrypt_login_key = base64_decode(request_data["login_key"]) login_key = aes_cbc_decrypt(encrypt_login_key, aes_key)[16:].decode() encrypt_login_passwd = base64_decode(request_data["login_passwd"]) login_passwd = aes_cbc_decrypt(encrypt_login_passwd, aes_key)[16:].decode() logger.debug(f"{login_key=} {login_passwd=}") user = SdoUser.get_or_none(user_id=login_key, # why not sifkey??? ticket=login_passwd) if not user: raise SanicException("Auth failed", status_code=403) login_resp = { "response_data": { "authorize_token": authorize_token, "user_id": user.user_id, "review_version": "", "server_timestamp": int(time.time()), "idfa_enabled": False, "skip_login_news": False, "adult_flag": 2 }, "release_info": {}, "status_code": 200 } x_message_sign = base64_encode( rsa_sha1_sign(jsonlib.dumps(login_resp).encode(), get_rsa_privkey())) logger.debug(f"{login_resp=} {x_message_sign=}") return json(login_resp, headers={ "X-Message-Sign": x_message_sign })