Example #1
0
 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)
Example #2
0
 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)
Example #3
0
 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)
Example #4
0
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"
Example #5
0
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'
Example #6
0
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')
Example #7
0
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')
Example #8
0
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')
Example #9
0
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')
Example #10
0
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)
Example #11
0
            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)
Example #12
0
            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")