def test_hash_fast(self, password): """ Hash various passwords as cheaply as possible. """ hash_password( password, salt=b"12345678", time_cost=1, memory_cost=8, parallelism=1, hash_len=8, )
def test_random_salt(self): """ Omitting a salt, creates a random one. """ rv = hash_password(b"secret") salt = rv.split(b",")[-1].split(b"$")[1] assert ( # -1 for not NUL byte int(_encoded_str_len(DEFAULT_RANDOM_SALT_LENGTH)) - 1 == len(salt))
def test_random_salt(self): """ Omitting a salt, creates a random one. """ rv = hash_password(b"secret") salt = rv.split(b",")[-1].split(b"$")[1] assert ( # -1 for not NUL byte int(_encoded_str_len(DEFAULT_RANDOM_SALT_LENGTH)) - 1 == len(salt) )
def _create_test_user(sql): """quick and dirty way to create a user to test logging in with. email: [email protected] password: hunter2 """ sql( "INSERT INTO users (name, email, password) VALUES ('test user', " "'*****@*****.**', :password)", password=argon2.hash_password(b"hunter2").decode(), )
def test_hash_password(self, type, hash): """ Creates the same encoded hash as the Argon2 CLI client. """ rv = hash_password( TEST_PASSWORD, TEST_SALT, TEST_TIME, TEST_MEMORY, TEST_PARALLELISM, TEST_HASH_LEN, type, ) assert hash == rv assert isinstance(rv, bytes)
def test_illegal_argon2_parameter(self): """ Raises HashingError if hashing fails. """ with pytest.raises(HashingError): hash_password(TEST_PASSWORD, memory_cost=1)
def test_hash_wrong_arg_type(self): """ Passing an argument of wrong type raises TypeError. """ with pytest.raises(TypeError): hash_password(u"oh no, unicode!")
def test_hash_defaults(self): """ Calling without arguments works. """ hash_password(b"secret")
def add_user(username: str, password: bytes, level=500): passwd = argon2.hash_password(password, secrets.token_bytes(None)) user = Users(username, passwd, level) db.session.add(user) db.session.commit()
def add(username, original_password, display_name, plain_text=True): Global.cursor.execute( "SELECT TRUE FROM Account WHERE username = %s", (username,) ) if len(Global.cursor.fetchall()) > 0: error_message = "user \"" + username + "\" already exists" logging.error(error_message) return False, error_message salt = secrets.token_hex(int(16/2)) ## each byte gets converted to two hex digits sha_function = Global.config.get("miscellaneous", "sha_function") if sha_function.upper().startswith("SHA3"): hash_function = getattr(hashlib, sha_function.lower().replace("-", "_")) else: hash_function = getattr(hashlib, sha_function.lower().replace("-", "")) if plain_text: hashed_password = hash_function(original_password.encode(Global.encoding)).hexdigest() else: hashed_password = original_password salt_method = Global.config.get("miscellaneous", "salt_method") try: if salt_method.upper().startswith("SHA"): hash = hash_function(hashed_password.encode(Global.encoding) + salt.encode(Global.encoding)).hexdigest() Global.cursor.execute( "INSERT INTO Account (username, displayName, salt, hash) VALUES (%s, %s, %s, %s);", (username, display_name, salt, hash) ) elif salt_method.lower() == "argon2": ## https://argon2-cffi.readthedocs.io/en/stable/argon2.html ## don't change type because Type.ID is the most secure, other parameters may be changed without resetting/migrating the database hash = argon2.hash_password( password=hashed_password.encode(Global.encoding), salt=salt.encode(Global.encoding), time_cost=DEFAULT_TIME_COST, memory_cost=DEFAULT_MEMORY_COST, parallelism=DEFAULT_PARALLELISM, hash_len=DEFAULT_HASH_LENGTH, type=Type.ID, ).decode(Global.encoding) Global.cursor.execute( "INSERT INTO Account (username, displayName, hash) VALUES (%s, %s, %s);", (username, display_name, hash) ) else: logging.critical("Salt method is invalid.") raise Exception except mysql.connector.DataError as e: ## db.rollback() if one of many commits fail (ACID property) assert "data too long" in e.msg.lower() error_message = "username must be 15 or less characters" logging.error(error_message) return False, error_message print() logging.debug("Added new account to database:") logging.debug(" Username: "******" Password: "******" Hashed Password: "******"argon2": logging.debug(" Salt: " + salt) else: logging.debug(" Embedded Salt: " + salt) logging.debug(" Hash: " + hash) print() return True, ""