def derivate(self): """ On presuppose qu'il y'a deja eu un appel de self.trade""" self.raw_secret = self.secret self.secret = HKDF(algorithm=hashes.SHA512(), length=len(self.raw_secret), salt=None, info=b"Je suis le roi des Chameaux", backend=backend()).derive(self.raw_secret)
def __init__(self,curve=ec.SECP256K1(),hash_for_derivation=hashes.SHA512()): self.curve = curve self.hash = hash_for_derivation self.pr_key = ec.generate_private_key(self.curve,backend()) # Du type cryptography.hazmat.backends.openssl.ec._EllipticCurvePublicKey self.pu_key = self.pr_key.public_key() # Au format x962 compressé -> b'0x04.....' self.pu_key_compressed = self.pu_key.public_bytes(Encoding.X962,PublicFormat.CompressedPoint)
def trade(self, peer_key): # On ne garde que la forme non compressé -> cryptography.hazmat.backends.openssl.ec._EllipticCurvePublicKey if type(peer_key == bytes): peer_key = ec.EllipticCurvePublicKey.from_encoded_point( self.curve, peer_key) self.peer_key = peer_key self.raw_secret = self.pr_key.exchange(ec.ECDH(), peer_key) self.secret = HKDF(algorithm=self.hash, length=len(self.raw_secret), salt=None, info=b"Je suis le roi des Chameaux", backend=backend()).derive(self.raw_secret)
async def ingameRegistration(request: Request) -> Union[dict, bytes]: start = time.time() mpargs = request.args name = mpargs["user[username]"].strip() # what is this setup osu lol email = mpargs["user[user_email]"].strip() pw = mpargs["user[password]"].strip() if not mpargs.get("check") or not all((name, email, pw)): return b"missing required paramaters" errors = defaultdict(list) if " " in name and "_" in name: errors["username"].append('Username cannot contain both "_" and " "') if await glob.db.fetchval("SELECT 1 FROM users WHERE name = %s", [name]): errors["username"].append("Username already taken!") if await glob.db.fetchval("SELECT 1 FROM users WHERE email = %s", [email]): errors["user_email"].append("Email already in use!") if not len(pw) >= 8: errors["password"].append("Password must be 8+ characters!") if errors: return {"form_error": {"user": errors}} if int(mpargs["check"]) == 0: md5 = hashlib.md5(pw.encode()).hexdigest().encode() k = HKDFExpand( algorithm=hashes.SHA256(), length=32, info=b"", backend=backend(), ) bc = k.derive(md5).decode("unicode-escape") glob.cache["pw"][bc] = md5 uid = await glob.db.execute( "INSERT INTO users (name, email, pw, safe_name, registered_at) VALUES (%s, %s, %s, %s, %s)", [name, email, bc, name.lower().replace(" ", "_"), time.time()], ) await glob.db.execute("INSERT INTO stats (id) VALUES (%s)", [uid]) info( f"{name} successfully registered. | Time Elapsed: {(time.time() - start) * 1000:.2f}ms", ) return b"ok"
async def ingameRegistration(request: Request) -> Union[dict, bytes]: start = time.time() mpargs = request.args name = mpargs['user[username]'].strip() # what is this setup osu lol email = mpargs['user[user_email]'].strip() pw = mpargs['user[password]'].strip() if not mpargs.get('check') or not all((name, email, pw)): return b'missing required paramaters' errors = defaultdict(list) if ' ' in name and '_' in name: errors['username'].append('Username cannot contain both "_" and " "') if await glob.db.fetchval("SELECT 1 FROM users WHERE name = %s", [name]): errors['username'].append('Username already taken!') if await glob.db.fetchval("SELECT 1 FROM users WHERE name = %s", [email]): errors['user_email'].append('Email already in use!') if not len(pw) >= 8: errors['password'].append('Password must be 8+ characters!') if errors: return {'form_error': {'user': errors}} if int(mpargs['check']) == 0: md5 = hashlib.md5(pw.encode()).hexdigest().encode() k = HKDFExpand(algorithm=hashes.SHA256(), length=32, info=b'', backend=backend()) bc = k.derive(md5).decode('unicode-escape') glob.cache['pw'][bc] = md5 uid = await glob.db.execute( "INSERT INTO users (name, email, pw, safe_name, registered_at) VALUES (%s, %s, %s, %s, %s)", [name, email, bc, name.lower().replace(' ', '_'), time.time()]) await glob.db.execute('INSERT INTO stats (id) VALUES (%s)', [uid]) log( f'{name} successfully registered. | Time Elapsed: {(time.time() - start) * 1000:.2f}ms', Ansi.LBLUE) return b'ok'
def aes_ecb_decrypt(ctext, key): cipher = Cipher(algorithms.AES(key), modes.ECB(), backend()).decryptor() blockdata = cipher.update(ctext) + cipher.finalize() bytesdata = blockdata[:-int(blockdata[-1])] # padding return bytesdata.decode('utf-8')
async def register_post(): if 'authenticated' in session: return await flash('error', "You're already logged in.", 'home') if not glob.config.registration: return await flash('error', 'Registrations are currently disabled.', 'home') form = await request.form username = form.get('username', type=str) email = form.get('email', type=str) passwd_txt = form.get('password', type=str) if username is None or email is None or passwd_txt is None: return await flash('error', 'Invalid parameters.', 'home') if glob.config.hCaptcha_sitekey != 'changeme': captcha_data = form.get('h-captcha-response', type=str) if ( captcha_data is None or not await utils.validate_captcha(captcha_data) ): return await flash('error', 'Captcha failed.', 'register') # Usernames must: # - be within 2-15 characters in length # - not contain both ' ' and '_', one is fine # - not be in the config's `disallowed_names` list # - not already be taken by another player # check if username exists if not regexes.username.match(username): return await flash('error', 'Invalid username syntax.', 'register') if '_' in username and ' ' in username: return await flash('error', 'Username may contain "_" or " ", but not both.', 'register') if username in glob.config.disallowed_names: return await flash('error', 'Disallowed username; pick another.', 'register') if await glob.db.fetch('SELECT 1 FROM users WHERE name = %s', username): return await flash('error', 'Username already taken by another user.', 'register') # Emails must: # - match the regex `^[^@\s]{1,200}@[^@\s\.]{1,30}\.[^@\.\s]{1,24}$` # - not already be taken by another player if not regexes.email.match(email): return await flash('error', 'Invalid email syntax.', 'register') if await glob.db.fetch('SELECT 1 FROM users WHERE email = %s', email): return await flash('error', 'Email already taken by another user.', 'register') # Passwords must: # - be within 8-32 characters in length # - have more than 3 unique characters # - not be in the config's `disallowed_passwords` list if not 8 <= len(passwd_txt) <= 32: return await flash('error', 'Password must be 8-32 characters in length.', 'register') if len(set(passwd_txt)) <= 3: return await flash('error', 'Password must have more than 3 unique characters.', 'register') if passwd_txt.lower() in glob.config.disallowed_passwords: return await flash('error', 'That password was deemed too simple.', 'register') # TODO: add correct locking # (start of lock) pw_md5 = hashlib.md5(passwd_txt.encode()).hexdigest().encode() k = HKDFExpand(algorithm=hashes.SHA256(), length=32, info=b'', backend=backend()) pw_hash = k.derive(pw_md5).decode('unicode-escape') glob.cache['pw'][pw_hash] = pw_md5 # cache pw safe_name = utils.get_safe_name(username) # fetch the users' country if 'CF-Connecting-IP' in request.headers: ip = request.headers['CF-Connecting-IP'] else: ip = request.headers['X-Forwarded-For'].split(',')[0] try: country = await utils.fetch_geoloc(ip) except: country = 'xx' user = await glob.db.execute( 'INSERT INTO users ' '(name, safe_name, email, pw, country, registered_at) ' 'VALUES (%s, %s, %s, %s, %s, UNIX_TIMESTAMP())', [username, safe_name, email, pw_hash, country] ) user_id = user # add to `stats` table. await glob.db.execute( 'INSERT INTO stats ' '(id) VALUES (%s)', user_id ) # (end of lock) if glob.config.debug: log(f'{username} has registered - awaiting verification.', Ansi.LGREEN) # user has successfully registered return await render_template('verify.html')
async def login_post(): if 'authenticated' in session: return await flash('error', "You're already logged in!", 'home') if glob.config.debug: login_time = time.time_ns() form = await request.form username = form.get('username', type=str) passwd_txt = form.get('password', type=str) if username is None or passwd_txt is None: return await flash('error', 'Invalid parameters.', 'home') # check if account exists user_info = await glob.db.fetchrow( 'SELECT id, name, email, priv, ' 'pw, silence_end ' 'FROM users ' 'WHERE safe_name = %s', [utils.get_safe_name(username)] ) # user doesn't exist; deny post # NOTE: Bot isn't a user. if not user_info or user_info['id'] == 1: if glob.config.debug: log(f"{username}'s login failed - account doesn't exist.", Ansi.LYELLOW) return await flash('error', 'Account does not exist.', 'login') # cache and other related password information pw_cache = glob.cache['pw'] pw_hash = user_info['pw'].encode('ISO-8859-1').decode('unicode-escape').encode('ISO-8859-1') pw_md5 = hashlib.md5(passwd_txt.encode()).hexdigest().encode() # check credentials (password) against db # intentionally slow, will cache to speed up if pw_hash in pw_cache: if pw_md5 != pw_cache[pw_hash]: # ~0.1ms if glob.config.debug: log(f"{username}'s login failed - pw incorrect.", Ansi.LYELLOW) return await flash('error', 'Password is incorrect.', 'login') else: # ~200ms k = HKDFExpand(algorithm=hashes.SHA256(), length=32, info=b'', backend=backend()) try: k.verify(pw_md5, pw_hash) except: if glob.config.debug: log(f"{username}'s login failed - pw incorrect.", Ansi.LYELLOW) return await flash('error', 'Password is incorrect.', 'login') # login successful; cache password for next login pw_cache[pw_hash] = pw_md5 # user not verified; render verify if not user_info['priv'] & Privileges.Verified: if glob.config.debug: log(f"{username}'s login failed - not verified.", Ansi.LYELLOW) return await render_template('verify.html') # user banned; deny post if user_info['priv'] & Privileges.Disallowed: if glob.config.debug: log(f"{username}'s login failed - banned.", Ansi.RED) return await flash('error', 'Your account is restricted. You are not allowed to log in.', 'login') # login successful; store session data if glob.config.debug: log(f"{username}'s login succeeded.", Ansi.LGREEN) session['authenticated'] = True session['user_data'] = { 'id': user_info['id'], 'name': user_info['name'], 'email': user_info['email'], 'priv': user_info['priv'], 'silence_end': user_info['silence_end'], 'is_staff': user_info['priv'] & Privileges.Staff, 'is_donator': user_info['priv'] & Privileges.Supporter } if glob.config.debug: login_time = (time.time_ns() - login_time) / 1e6 log(f'Login took {login_time:.2f}ms!', Ansi.LYELLOW) return await flash('success', f'Hey, welcome back {username}!', 'home')
async def settings_password_post(): form = await request.form old_password = form.get('old_password') new_password = form.get('new_password') repeat_password = form.get('repeat_password') # new password and repeat password don't match; deny post if new_password != repeat_password: return await flash('error', "Your new password doesn't match your repeated password!", 'settings/password') # new password and old password match; deny post if old_password == new_password: return await flash('error', 'Your new password cannot be the same as your old password!', 'settings/password') # Passwords must: # - be within 8-32 characters in length # - have more than 3 unique characters # - not be in the config's `disallowed_passwords` list if not 8 < len(new_password) <= 32: return await flash('error', 'Your new password must be 8-32 characters in length.', 'settings/password') if len(set(new_password)) <= 3: return await flash('error', 'Your new password must have more than 3 unique characters.', 'settings/password') if new_password.lower() in glob.config.disallowed_passwords: return await flash('error', 'Your new password was deemed too simple.', 'settings/password') # cache and other password related information pw_cache = glob.cache['pw'] pw_hash = (await glob.db.fetchval( 'SELECT pw ' 'FROM users ' 'WHERE id = %s', [session['user_data']['id']]) ).encode('ISO-8859-1').decode('unicode-escape').encode('ISO-8859-1') pw_md5 = hashlib.md5(old_password.encode()).hexdigest().encode() # check old password against db # intentionally slow, will cache to speed up if pw_hash in pw_cache: if pw_md5 != pw_cache[pw_hash]: # ~0.1ms if glob.config.debug: log(f"{session['user_data']['name']}'s change pw failed - pw incorrect.", Ansi.LYELLOW) return await flash('error', 'Your old password is incorrect.', 'settings/password') else: # ~200ms k = HKDFExpand(algorithm=hashes.SHA256(), length=32, info=b'', backend=backend()) try: k.verify(pw_hash, pw_md5) except: if glob.config.debug: log(f"{session['user_data']['name']}'s change pw failed - pw incorrect.", Ansi.LYELLOW) return await flash('error', 'Your old password is incorrect.', 'settings/password') # remove old password from cache if pw_hash in pw_cache: del pw_cache[pw_hash] # calculate new md5 & bcrypt pw pw_md5 = hashlib.md5(new_password.encode()).hexdigest().encode() k = HKDFExpand(algorithm=hashes.SHA256(), length=32, info=b'', backend=backend()) pw_hash_new = k.derive(pw_md5).decode('unicode-escape') # update password in cache and db pw_cache[pw_hash_new] = pw_md5 await glob.db.execute( 'UPDATE users ' 'SET pw = %s ' 'WHERE safe_name = %s', [pw_hash_new, utils.get_safe_name(session['user_data']['name'])] ) # logout session.pop('authenticated', None) session.pop('user_data', None) return await flash('success', 'Your password has been changed! Please log in again.', 'login')
from cryptography.hazmat.backends import default_backend as backend from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives import hashes private_key = rsa.generate_private_key(public_exponent=65537, key_size=4096, backend=backend()) #public_key = private_key.public_key public_key = private_key.public_key() message = b"More secrets go here" encrypted = public_key( message, padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)) print(encrypted) decrypted = private_key.decrypt( encrypted, padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()), algorithm=hashes.SHA256(), label=None)) print(decrypted)
request.resp_headers['cho-token'] = 'no' # client knows there is something up if we set token to 'no' return writer.userID(-1) # if server is migrated then passwords are previously stored as bcrypt # lets check if we need to convert and do so if needed if glob.config.server_migration and ('$' in user['pw'] and len(user['pw']) == 60): user_pw = user['pw'].encode() if not bcrypt.checkpw(pw, user_pw): if glob.config.debug: log(f"{username}'s login attempt failed: provided an incorrect password", Ansi.LRED) request.resp_headers['cho-token'] = 'no' # client knows there is something up if we set token to 'no' return writer.userID(-1) else: # correct password, we allow the user to continue but lets convert the password to our new format first k = HKDFExpand(algorithm=hashes.SHA256(), length=32, info=b'', backend=backend()) new_pw = k.derive(pw).decode('unicode-escape') await glob.db.execute('UPDATE users SET pw = %s WHERE id = %s', [new_pw, user['id']]) # add to cache for the future glob.cache['pw'][new_pw] = pw else: # password is already converted or db already has correct formats bcache = glob.cache['pw'] # get our cached pws to potentially enhance speed user_pw = user['pw'].encode('ISO-8859-1').decode('unicode-escape').encode('ISO-8859-1') # this is cursed SHUT UP if user_pw in bcache: if pw != bcache[user_pw]: # compare provided md5 with the stored (cached) pw to ensure they have provided the correct password if glob.config.debug: log(f"{username}'s login attempt failed: provided an incorrect password", Ansi.LRED)
user_pw = user["pw"].encode() if not bcrypt.checkpw(pw, user_pw): warning( f"{username}'s login attempt failed: provided an incorrect password", ) request.resp_headers[ "cho-token" ] = "no" # client knows there is something up if we set token to 'no' return writer.userID(-1) else: # correct password, we allow the user to continue but lets convert the password to our new format first k = HKDFExpand( algorithm=hashes.SHA256(), length=32, info=b"", backend=backend(), ) new_pw = k.derive(pw).decode("unicode-escape") await glob.db.execute( "UPDATE users SET pw = %s WHERE id = %s", [new_pw, user["id"]], ) # add to cache for the future glob.cache["pw"][new_pw] = pw else: # password is already converted or db already has correct formats bcache = glob.cache["pw"] # get our cached pws to potentially enhance speed user_pw = ( user["pw"] .encode("ISO-8859-1")