def run(x): input = 'c79855a0f5344b655b8bc30220b545e2ef25b88b723745b7fed976d46e260c91' # hash of https://is.gd/Bartha result = 0 count = 0 while result < x: salt = str(secrets.randbits(257)) result = divide(binascii.hexlify(argon2.argon2_hash(input,salt))) data = binascii.hexlify(argon2.argon2_hash(input,salt)) count += 1 # return [str(data)[2:-1], int(salt), count] return [int(salt), count]
def authenticate(username: str, password: str) -> str: """ This method is used to authenticate a user using their credentials. If the authentication process is successful, a user token is generated and published to the user_cache. The user token is also returned by this method so that it can be passed to the client as a response. If the user couldn't be authenticated, an empty string is returned. :param username: The user's username :param password: The user's password :return: The user's token """ user = users.get(username) if user is None: del password return "" hash_result = argon2.argon2_hash(password, user.password_salt) del password if hash_result == user.password_hash: user_token = os.urandom(64).hex() while user_cache.exists(user_token): user_token = os.urandom(64).hex() pub('user_authenticated', user_token, username, user.privilege_level, config.get('user_ttl')) return user_token return ""
def _hash_argon2(self, username, pwd, salt=None): """Hash username and password, generating salt value if required Use argon2 :returns: base-64 encoded string. """ if not argon2_available: raise Exception("argon2 required." " Please install the argon2 library.") if salt is None: salt = os.urandom(self.saltlength['argon2']) assert len(salt) == self.saltlength['argon2'], \ "Incorrect salt length %s" % salt cleartext = "%s\0%s" % (username, pwd) # t = time cost (# of iterations) # m = memory cost kilobytes # p = parallelism degree (# parallel threads) h = argon2.argon2_hash(cleartext, salt, t=31, m=31, p=2) # 'a' for argon2 hashed = b'a' + salt + h return b64encode(hashed)
def users_add(): """ Register a new user Example: requests.post("api/users/add", data={ "username": "******", "password": "******" }) """ username = request.json.get("username") password = request.json.get("password") if not (username and password): return jsonify({ "success": False, "message": "username and password must not be empty" }) if _exists(users, {"username": username}): return jsonify({ "success": False, "message": "A user with this username already exists" }) users.insert_one({ "username": username, "password": argon2.argon2_hash(password, self.salt) }) return jsonify({"success": True, "message": "User created"})
def loginUser(username, password): loginResult = False jsonPassword = "" jsonSalt = "" with open(CREDENTIALS, "r") as file: try: fileContents = json.load(file) # see if username exists, if not, access denied if not (fileContents[username]): loginUser = False else: jsonPassword = fileContents[username]["password"] jsonSalt = fileContents[username]["salt"] # hash given password using argon2 hashedPassword = str( argon2.argon2_hash(password=password, salt=jsonSalt)) # check if stored (hashed) password is same as the hashed inputted password if jsonPassword == hashedPassword: loginUser = True else: loginUser = False except: # if file fails to read, access denied accessDenied() return loginUser
def register_user(param): conn = None try: conn = MySQLdb.connect('localhost', 'testuser', 'xxxx', 'cs_bank_2') salt = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(20)) passw = argon2.argon2_hash( password=param['password'], salt=salt, t=16, m=8, p=1, buflen=128, argon_type=argon2.Argon2Type.Argon2_i).decode("ISO-8859-15") sql = "insert into users (FirstName, LastName, Email, UserName, City, Address, Password, Salt) values ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')" % ( param['firstname'], param['lastname'], param['email'], param['username'], param['city'], param['address'], passw, salt) print(sql, '\n') cursor = conn.cursor(MySQLdb.cursors.DictCursor) cursor.execute(sql) conn.commit() except MySQLdb.Error as e: print('error {}: {}'.format(e.args[0], e.args[1])) return False finally: if conn: conn.close() return True
def banklogin(): if request.method == 'GET': return redirect("/onlinebanking") username = request.form.get('username') password = request.form.get('password') new_session_value = '' current_user = '' action_login = True for user in users: if str(username) == user['username'] and base64.b64decode( user['password_hash']) == argon2.argon2_hash( password=str(password), salt=user['salt'], t=16, m=8, p=1, buflen=128, argon_type=argon2.Argon2Type.Argon2_i): new_session_value = str(uuid.uuid4()) user['session'] = new_session_value current_user = user['username'] action_login = False break resp = make_response( render_template('onlinebanking.html', transactions=transactions, current_user=current_user, action_login=action_login)) resp.set_cookie('session-cookie', new_session_value) return resp
def accepted(username, password): userData = {} fileContents = {} # read file, even if it's empty with open(CREDENTIALS, "r") as outfile: # check if file is empty # this try-catch needs to be here, or else if reading # an empty file, program will crash try: fileContents = json.load(outfile) except: '''do nothing''' # generate unique salt for user salt = generateSalt() hashedPassword = str(argon2.argon2_hash(password=password, salt=salt)) userData[username] = {"password": hashedPassword, "salt": salt} fileContents.update(userData) # write updates to credential file with open("credentials.json", "w") as outfile: json.dump(fileContents, outfile) print(ACCEPTED)
def _hash_argon2(self, username, pwd, salt=None): """Hash username and password, generating salt value if required Use argon2 :returns: base-64 encoded string. """ if not argon2_available: raise Exception("argon2 required." " Please install the argon2 library.") if salt is None: salt = os.urandom(self.saltlength['argon2']) assert len(salt) == self.saltlength['argon2'], "Incorrect salt length %s" % salt cleartext = "%s\0%s" % (username, pwd) # t = time cost (# of iterations) # m = memory cost kilobytes # p = parallelism degree (# parallel threads) h = argon2.argon2_hash(cleartext, salt, t=31, m=31, p=2) # 'a' for argon2 hashed = b'a' + salt + h return b64encode(hashed)
def SlowKDF(input_passphrase, input_salt, memory, iterations): beginning = time() xor_digest=sha512(input_passphrase+input_salt).digest() xor_digest+=sha512(xor_digest+input_salt+input_passphrase).digest() digest=sha512(input_salt+input_passphrase+xor_digest).digest() digest=sha3_512(digest).digest() start = time() for counter in range(iterations): print ("Iteration %s from %s..." % (counter+1, iterations) ) shahehehe=sha512(xor_digest+input_passphrase+input_salt+digest).digest() # The passphrase (shahehehe) size of scrypt should be equal to the block size of the SHA-256 (64 bytes) # to avoid the initial hashing with SHA-256 if the password is longer or shorter (HMAC-SHA256). # Block size should not be confused with the digest size (for SHA-256 the block size is 64 bytes, the digest size is 32 bytes). print (" Computing Scrypt...") digest=scrypt.hash(shahehehe, input_salt, N = memory, r = 8, p = 1, buflen = 128) xor_digest=strxor(xor_digest, digest) shahehehe=sha512(xor_digest+input_passphrase+input_salt+digest).digest() kek=sha3_512(shahehehe).digest() print (" Computing Argon2d...") digest=argon2.argon2_hash(password=digest+shahehehe+xor_digest+kek, salt=input_salt, t=1, m=memory, p=1, buflen=128, argon_type=argon2.Argon2Type.Argon2_d) xor_digest=strxor(xor_digest, digest) current = time() diff=current - start estimated_total = (diff / (counter + 1) ) * iterations print (" Elapsed time:", TimeToString(current - beginning)) if counter+1 < iterations: print (" Estimated remaining time:", TimeToString(estimated_total - diff) ) kek=sha3_512(xor_digest+input_passphrase+input_salt+digest).digest() shahehehe=sha512(kek+digest+input_passphrase+input_salt+xor_digest).digest() kek2=sha3_512(kek+shahehehe+digest+input_passphrase+input_salt+xor_digest).digest() shahehehe=sha512(kek2+kek+shahehehe).digest() current = time() print (" Elapsed time:", TimeToString(current - beginning)) return shahehehe
def register(username: str, password: str, privilege_level: int) -> bool: """ Registers a new user. Checks, if the user already exists and only registers a new one, if the username isn't already taken. :param username: The new user's username :param password: The new user's password :param privilege_level: The new user's privilege level :return: Whether the new user was registered or not """ password_salt = os.urandom(512) password_hashed = argon2.argon2_hash(password, password_salt) del password if users.get(username) is not None: return False user = users.create(username, password_hashed, password_salt) with persistance(): user.privilege_level = privilege_level user_token = os.urandom(64).hex() while user_cache.exists(user_token): user_token = os.urandom(64).hex() pub('user_authenticated', user_token, username, user.privilege_level, config.get('user_ttl')) return True
def enroll(username): enrolledUsers = {} try: enrolledUsers = json.load(open('enrolled.json')) except: "" salt = generate_salt() ## key stretching: to be stored in password file ## the digest ## keep this digest for authentication and store the hash chain into the password file digest = str(argon2.argon2_hash(password, salt)) ## key strengthening #strongDigest = str(argon2.argon2_hash(digest, salt, 100)) ## store the digest into the password file and write it enrolledUsers[username] = { #"PASSWORD": hashedPwd, "SALT": salt "PASSWORD": digest, "SALT": salt } enrolledUsers.update(enrolledUsers) with open("enrolled.json", 'w') as out: json.dump(enrolledUsers, out)
def update_password(usergroup, password): password_salt = os.urandom(512) password_hashed = argon2.argon2_hash(password, password_salt) del password usergroup.password_salt = password_salt usergroup.password_hash = password_hashed
def to_hash(password, salt=None): if not salt: salt = os.urandom(20) phash = argon2.argon2_hash(password=password, salt=salt, t=argon_settings["t"], m=argon_settings["m"], p=argon_settings["p"]) return [phash, salt]
def hashPassword(password, salt, algo='argon2', params={'t': 5}): if algo == 'argon2': return binascii.hexlify( argon2.argon2_hash(password, salt, **params)).decode() else: raise ValueError('Unknown algorithm "%s".' % algo)
def hashAndEncrypt(self, password, key): dk = hashlib.pbkdf2_hmac(hash_name='sha384', password=password.encode(), salt=b'', iterations=100000) hash = binascii.hexlify(dk) hash = base64.b64encode(hash) cryp = argon2.argon2_hash(hash, key) return (cryp)
def register_usergroup(name, password_plain): password_salt = os.urandom(512) password_hashed = argon2.argon2_hash(password_plain, password_salt) del password_plain if usergroup_by_name(name) is not None: raise Exception("user already exists") return new_usergroup(name, password_salt, password_hashed)
def hashed_password(password: str, salt: str = None) -> (str, str): ''' Prepares typed-in password to be dumped to the db. Basically it's just: sha256(sha256(password) + salt) with some sort of permutations. I'm not considering using of the pepper thing because of its several flaws that make it pretty much useless. Read more at https://stackoverflow.com/a/16896216 ''' salt = salt if salt else token_hex(salt_length) return (argon2_hash(password, salt).hex(), salt)
def test_simple_call(self): actual = argon2.argon2_hash("password", "some_salt", ) self.assertEqual( actual, (b'\xa8&x\xc7\xd9\xc4\x1f\xdf[2\xd9hq\xab\xe5\xb4WV\x89\xca\xa4\xee\xb3\x98\xf1I\xd1' b'\xdaf\xe7=\xfaA\x04\xeb\xe1\xfd\x94)\xad\x84\r\x9ed<8xE\xc3\xd3\xfb\x13\xcbN\xcf\\}' b'\xfd-9\x8b\x07@\xd8\x10\x1a\x83\x05\xd5\xfd\xc4m\x9f\xd7\x81\xdcX\x87\xb2\x02\xa9R' b'\xc1\x9d\xaf6\xbb\x8c\xe1vH+\x07\xc7Y\x80\xb3\xb5\xf8\xba\xbd\x87\xd8\xf5\xea\x1a' b'\x04V&\xf7\xde\x9b\x93\x8dbQ\x91e\xf6\xd6\xa2\xd8G8\xe3\x9a\x03\xf3'))
def test_specified_call(self): actual = argon2.argon2_hash(password="******", salt="some salt", t=16, m=8, p=1, buflen=128, argon_type=argon2.Argon2Type.Argon2_i) self.assertEqual( actual, (b"\x1f>\xe0\xb8\x88%\xef\xee\xb3n\\\xb85\x03\x14\xb8\xb8O\x02Zk\xbf<\xd5\xa0C\xf2,p" b"\x00\xda\xd7Bc\xa71\x84\x10\x00\x8cx'\xec?Q\x8499\x9b\xd4)\xf1\x98F\x13!\x8bB\x12!" b"\xc3U\x8d\x9a\xb5\x10\x8cIo\xd2p\xcd'\x8c\x96d\xa5?{\x1d*\xaf\xab\x99\x9e\xe9c\xa4" b"\xb7\xb2\x00\xfa\x82\x96/\xdei_1Nun\x92j\n\xf3D#\x05\tj\xa2\x92\xd5\xf4nym\xd1Kq" b"\xa1|\xd19\xa9Q8"))
def create(name, email, password, address, postal_code): s = urandom(16) ph = argon2.argon2_hash(password, s) Users.add(name=name, email=email, salt=s, pass_hash=ph, address=address, postal_code=postal_code)
def get_key(key): """ Query for a key from the database. """ mid_hash = b64encode( argon2_hash(password=key, salt=API_KEY_SALT, t=HASH_TIME_PARAM, m=HASH_MEMORY_PARAM, p=HASH_PARALLELIZATION_PARAM)).decode() return APIKey.objects.get(key=API_KEY_SALT + "$" + mid_hash) # pylint: disable=no-member
def login_route(): if request.method == "POST": if request.form.get('username') == username and base64.b64encode( argon2_hash(request.form.get('password'), salt)).decode('utf-8') == password: session['logged_in'] = True return redirect('/', code=303) flash("Invalid credentials!", category="error") return render_template("login.html")
def create(name, username, email, password, lang): s = urandom(16) ph = argon2.argon2_hash(password, s) return Users.add(name=name, username=username, email=email, salt=s, pass_hash=ph, lang=lang)
def make_hash(password, salt): """Generate a hash from a password and a salt.""" computed_hash = argon2.argon2_hash(password=password, salt=salt, t=TIME, m=MEM, p=PAR, buflen=SIZE, argon_type=ARGON_TYPE) return computed_hash
def _hash(self, string, salt): """ Hashes string with salt, argon2, and params from constants :param string: Thing to hash :param salt: Salt to hash it with :return: bytearray """ return argon2.argon2_hash(password=string, salt=salt, t=argon_settings["t"], m=argon_settings["m"], p=argon_settings["p"])
def _get_seed_argon2(passphrase): """ Given a string passphrase, generates a 64-byte seed. The expectations from the seed are that it 1. Is deterministic. 2. Is statistically uniform. 3. Is hard to compute. 4. Preserves the enthropy given (up to 64 bytes). """ from argon2 import argon2_hash return argon2_hash(passphrase, passphrase, t=4096, m=16, buflen=64)
def test_simple_call(self): actual = argon2.argon2_hash( "password", "some_salt", ) self.assertEqual(actual, ( b'\xa8&x\xc7\xd9\xc4\x1f\xdf[2\xd9hq\xab\xe5\xb4WV\x89\xca\xa4\xee\xb3\x98\xf1I\xd1' b'\xdaf\xe7=\xfaA\x04\xeb\xe1\xfd\x94)\xad\x84\r\x9ed<8xE\xc3\xd3\xfb\x13\xcbN\xcf\\}' b'\xfd-9\x8b\x07@\xd8\x10\x1a\x83\x05\xd5\xfd\xc4m\x9f\xd7\x81\xdcX\x87\xb2\x02\xa9R' b'\xc1\x9d\xaf6\xbb\x8c\xe1vH+\x07\xc7Y\x80\xb3\xb5\xf8\xba\xbd\x87\xd8\xf5\xea\x1a' b'\x04V&\xf7\xde\x9b\x93\x8dbQ\x91e\xf6\xd6\xa2\xd8G8\xe3\x9a\x03\xf3' ))
def authenticated(self, username: str, password: str) -> str: """ Validate user credentials and return user document ID :param username: Plaintext username :param password: Hashed password :return: user's document ID as string, "" if not authorized """ user_doc = self.users.find_one({"username": username}) if user_doc and (user_doc["password"] == argon2.argon2_hash(password, self.salt)): return str(user_doc["_id"]) return "" # Not authorized
def hash_password(password, salt=None): """ Returns a hash of a password. """ if salt is None: salt = b64encode(urandom(15)).decode() mid_hash = b64encode( argon2_hash(password=password, salt=salt, t=HASH_TIME_PARAM, m=HASH_MEMORY_PARAM, p=HASH_PARALLELIZATION_PARAM)).decode() return salt + "$" + mid_hash
def validatePassword(salt, password, pwdHash): """ Uses the stored salt and password hash (from password file) to validate the given password. Args: salt: Retrieved from password file using passed username from cmd line argument password: The password given via cmd line argument pwdHash: Retrieved from password file using passed username from cmd line argument """ if argon2.argon2_hash(password, salt) == pwdHash: accessGranted() else: accessDenied()
def create_api_key(params): """ ### Overview Create an API key for a user. Only administrators may create api keys for other users. ### Parameters allowed_api_calls (optional): A list of API calls that the API token can perform. If left empty, all of the user's permissions will be granted to the token. This may not specify any API call that the user does not currently have access to. <list> user_context (optional, requires administrator) <str> """ # Retrieve the current user object (Allowing for administrator overrides) user, allowed_methods, _ = get_context(params) # Set the owner of the new API key to be the current user owner = user.username allowed_api_calls = params.get('allowed_api_calls') # Verify allowed api calls if allowed_api_calls: if any(method not in allowed_methods for method in allowed_api_calls): if '*' not in allowed_methods: raise PermissionDenied( 'Cannot create API key with more permissions than key owner.' ) else: allowed_api_calls = allowed_methods # Create the key original_key = '{}{}{}{}{}'.format( str(uuid4()), str(uuid4()), str(uuid4()), str(uuid4()), str(uuid4()), ) mid_hash = b64encode( argon2_hash(password=original_key, salt=API_KEY_SALT, t=HASH_TIME_PARAM, m=HASH_MEMORY_PARAM, p=HASH_PARALLELIZATION_PARAM)).decode() key = APIKey(key=API_KEY_SALT + "$" + mid_hash, owner=owner, allowed_api_calls=allowed_api_calls) key.save(force_insert=True) return success_response(api_key=original_key)
def authenticate(): u = Users.query.filter_by(username=request.json["username"]).first() if u is None: return {"status": "fail", "error": ""} if u.password_hash == argon2.argon2_hash(request.json["password"], u.salt): g.user = u g.token = make_jwt( { "uid": u.id, "at": int(time.time()), "exp": int(time.time()) + 604800 }, app.config["SECRET_KEY"]) return {"status": "ok", "username": u.username} return {"status": "fail", "error": ""}
def generate_keys(key, salt, time, memory, distribution): """ generate and derive keys for encryption""" log("i", "Generating keys....") keys = [] keys.append(argon2.argon2_hash(key, salt, t=time, m=memory)) # Derive keys from Main Argon Key for i in range(0, distribution): keys.append(hashlib.sha256(keys[i]).digest()) # Remove argon base key keys.pop(0) return keys
def hash_secret_strong(s): """Hash secret, case-sensitive string to binary data. This is the strong version which should be used for passwords but not for huge data sets like indentification numbers. """ if not s: s = "" # WARNING: changing these parameter invalides the entire table! # INFO: buflen is in bytes, not bits! So this is a 256bit output # which is higher than the current (2015-12) recommendation # of 128bit. We use 2 lanes and 4MB of memory. 4 passes seems # to be a good choice. return argon2_hash(s.encode("utf8"), app.config["ARGON2_SALT"], buflen=32, t=4, p=2, m=(1 << 12))
def hash_secret_weak(s): """Hash secret, case-sensitive string to binary data. This is the weak version which should be used for large data sets like identifiers, but NOT for passwords! """ if not s: s = "" # WARNING: changing these parameter invalides the entire table! # INFO: buflen is in bytes, not bits! So this is a 256bit output # which is higher than the current (2015-12) recommendation # of 128bit. We use 2 lanes and 64KB of memory. One pass has # to be enough, because otherwise we need to much time while # importing. return argon2_hash(s.encode("utf8"), app.config["ARGON2_SALT"], buflen=32, t=1, p=2, m=(1 << 6))
def do_login(db): logged_in = check_token( request.get_cookie("token"), db ) username = request.forms.get('username') password = request.forms.get('password') user = db.execute('SELECT id,salt,password from users where username=?', (username,)).fetchone() if user == None: return dict(login='******', logged_in=logged_in) password = argon2_hash( password, user['salt'], buflen=32 ) password = hexlify(password).decode() if password != user['password']: return dict(login='******', logged_in=logged_in) token_random = Random.get_random_bytes(32) token = hexlify(token_random).decode() token_expiry = int(time.time()) + 3600 db.execute('UPDATE users SET token=?,token_expiry=? WHERE id=?', (token, token_expiry, user['id'])) response.set_cookie("token", token, max_age=3600, expires=token_expiry) # do max_age and expires really work? return dict(login='******', logged_in=logged_in)