diff --git a/backend/app.py b/backend/app.py index 368c529..00f82ba 100644 --- a/backend/app.py +++ b/backend/app.py @@ -65,11 +65,13 @@ def APP_STATUS(): return "init" if db.get("password") is None else "run" def JWT_SECRET(): return db.get("secret") def hash_psw(psw: str): - salt = db.get("salt") - if not salt: - salt = secrets.token_hex(32) - db.put("salt", salt) - return hashlib.pbkdf2_hmac("sha256", psw.encode(), salt.encode(), 500_000).hex() + salt = secrets.token_hex(32) + return hashlib.pbkdf2_hmac("sha256", psw.encode(), salt.encode(), 500_000).hex()+"-"+salt + +def verify_psw(psw: str, hashed: str) -> bool: + psw_hash, salt = hashed.split("-") + new_hashed = hashlib.pbkdf2_hmac("sha256", psw.encode(), salt.encode(), 500_000).hex() + return new_hashed == psw_hash def set_psw(psw: str): db.put("password", hash_psw(psw)) @@ -142,7 +144,7 @@ async def login_api(form: OAuth2PasswordRequestForm = Depends()): if form.password == "": return {"status":"Cannot insert an empty password!"} await asyncio.sleep(0.3) # No bruteforce :) - if db.get("password") == hash_psw(form.password): + if verify_psw(form.password, db.get("password")): return {"access_token": create_access_token({"logged_in": True}), "token_type": "bearer"} raise HTTPException(406,"Wrong password!") @@ -185,8 +187,8 @@ reset, startup, shutdown = load_routers(api) async def startup_main(): db.init() - if os.getenv("HEX_SET_PSW"): - set_psw(bytes.fromhex(os.getenv("HEX_SET_PSW")).decode()) + if os.getenv("PSW_HASH_SET"): + db.put("password", os.getenv("PSW_HASH_SET")) try: sysctl.set() except Exception as e: diff --git a/run.py b/run.py index d0f3c1e..31efba3 100755 --- a/run.py +++ b/run.py @@ -9,6 +9,8 @@ import multiprocessing import subprocess import getpass import tarfile +import hashlib +import secrets pref = "\033[" reset = f"{pref}0m" @@ -38,6 +40,10 @@ class colors: cyan = "36m" white = "37m" +def hash_psw(psw: str): + salt = secrets.token_hex(32) + return hashlib.pbkdf2_hmac("sha256", psw.encode(), salt.encode(), 500_000).hex()+"-"+salt + def puts(text, *args, color=colors.white, is_bold=False, **kwargs): print(f'{pref}{1 if is_bold else 0};{color}' + text + reset, *args, **kwargs) @@ -260,7 +266,7 @@ def write_compose(skip_password = True): f"PORT={args.port}", f"HOST={args.host}", f"NTHREADS={args.threads}", - *([f"HEX_SET_PSW={psw_set.encode().hex()}"] if psw_set else []) + *([f"PSW_HASH_SET={hash_psw(psw_set)}"] if psw_set else []) ], "volumes": [ "firegex_data:/execute/db", @@ -308,7 +314,7 @@ def write_compose(skip_password = True): "environment": [ f"PORT={args.port}", f"NTHREADS={args.threads}", - *([f"HEX_SET_PSW={psw_set.encode().hex()}"] if psw_set else []) + *([f"PSW_HASH_SET={hash_psw(psw_set)}"] if psw_set else []) ], "volumes": [ "firegex_data:/execute/db" @@ -760,7 +766,7 @@ def run_standalone(): # Add password if set psw_set = get_password() if psw_set: - env_vars.append(f"HEX_SET_PSW={psw_set.encode().hex()}") + env_vars.append(f"PSW_HASH_SET={hash_psw(psw_set)}") # Prepare environment string for chroot env_string = " ".join([f"{var}" for var in env_vars])