use a kdf
This commit is contained in:
parent
2cfa671338
commit
e070a96fb6
1 changed files with 32 additions and 5 deletions
37
tresetter.py
37
tresetter.py
|
@ -6,10 +6,12 @@ import json
|
|||
import uuid
|
||||
from subprocess import Popen, CalledProcessError, check_output
|
||||
from typing import Optional
|
||||
import hashlib
|
||||
import base64
|
||||
|
||||
import redis
|
||||
from fastapi import FastAPI, APIRouter, HTTPException, Cookie, Request
|
||||
from fastapi.responses import Response, JSONResponse, RedirectResponse
|
||||
from fastapi.responses import Response, RedirectResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from pydantic import BaseModel, BaseSettings
|
||||
|
||||
|
@ -201,22 +203,47 @@ async def logout(session_id: str = Cookie(None)) -> BaseModel:
|
|||
delete_session(session_id)
|
||||
return BaseModel()
|
||||
|
||||
KDF_SALT_SIZE = 16
|
||||
|
||||
|
||||
def kdf_gen(password, salt=None) -> str:
|
||||
if salt is None:
|
||||
salt = random.randbytes(KDF_SALT_SIZE)
|
||||
if hasattr(password, 'encode'):
|
||||
password = password.encode('utf8')
|
||||
raw = hashlib.scrypt(password, n=2, r=1, p=1, salt=salt)
|
||||
with_salt = salt + raw
|
||||
return base64.b64encode(with_salt).decode('ascii')
|
||||
|
||||
def kdf_get_salt(hashed: str):
|
||||
hashed_str = hashed.decode('ascii') if hasattr(hashed, 'decode') else hashed
|
||||
with_salt = base64.b64decode(hashed_str)
|
||||
salt = with_salt[:KDF_SALT_SIZE]
|
||||
return salt
|
||||
|
||||
def kdf_verify(hashed: str, password: str) -> bool:
|
||||
salt = kdf_get_salt(hashed)
|
||||
hashed2 = kdf_gen(password, salt=salt)
|
||||
return hashed == hashed2
|
||||
|
||||
|
||||
@router.post("/generate", tags=["password"])
|
||||
async def generate(session_id: str = Cookie(None)):
|
||||
session = get_session(session_id)
|
||||
session["proposed_password"] = password_generate()
|
||||
proposed_password = password_generate()
|
||||
session["proposed_password_hash"] = kdf_gen(proposed_password)
|
||||
set_session(session_id, session)
|
||||
|
||||
return ChangeData(password=session["proposed_password"])
|
||||
return ChangeData(password=proposed_password)
|
||||
|
||||
|
||||
@router.post("/change", tags=["password"])
|
||||
async def change(req: ChangeData, session_id: str = Cookie(None)) -> SuccessData:
|
||||
session = get_session(session_id)
|
||||
if "proposed_password" not in session:
|
||||
if "proposed_password_hash" not in session:
|
||||
raise HTTPException(status_code=400, detail="You must generate it first")
|
||||
if req.password != session["proposed_password"]:
|
||||
hashed = session["proposed_password_hash"]
|
||||
if not kdf_verify(hashed, req.password):
|
||||
raise HTTPException(status_code=409)
|
||||
|
||||
success = change_password(session["username"], req.password)
|
||||
|
|
Loading…
Reference in a new issue