You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
100 lines
3.5 KiB
100 lines
3.5 KiB
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
|
|
}) |