mirror of https://github.com/wg-easy/wg-easy
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
147 lines
5.1 KiB
147 lines
5.1 KiB
import bcrypt
|
|
import os
|
|
import json
|
|
|
|
def generate_salt(cost_factor: int = 12) -> str:
|
|
"""
|
|
Generates a random salt with a specified cost factor.
|
|
|
|
:param cost_factor: The cost factor for bcrypt (default is 12).
|
|
:return: A random salt as a hexadecimal string.
|
|
"""
|
|
return bcrypt.gensalt(cost_factor).decode('utf-8')
|
|
|
|
def hash_password(password: str, salt: str) -> str:
|
|
"""
|
|
Converts a password into a bcrypt hash with a salt.
|
|
|
|
:param password: The password to hash.
|
|
:param salt: The salt to use for hashing.
|
|
:return: The bcrypt hash of the password with the salt.
|
|
"""
|
|
return bcrypt.hashpw(password.encode(), salt.encode()).decode('utf-8')
|
|
|
|
def verify_password(hashed_password: str, password: str) -> bool:
|
|
"""
|
|
Verifies if the password matches the hash with the salt.
|
|
|
|
:param hashed_password: The bcrypt hash of the password with the salt.
|
|
:param password: The password to verify.
|
|
:return: True if the password matches the hash, False otherwise.
|
|
"""
|
|
return bcrypt.checkpw(password.encode(), hashed_password.encode())
|
|
|
|
def save_to_file(salt: str, hashed_password: str, filename: str):
|
|
"""
|
|
Saves the salt and hash to a file.
|
|
|
|
:param salt: The salt used for hashing.
|
|
:param hashed_password: The hash of the password.
|
|
:param filename: The name of the file to save the data.
|
|
"""
|
|
data = {
|
|
'salt': salt,
|
|
'hashed_password': hashed_password
|
|
}
|
|
with open(filename, 'w') as file:
|
|
json.dump(data, file)
|
|
|
|
def load_from_file(filename: str):
|
|
"""
|
|
Loads the salt and hash from a file.
|
|
|
|
:param filename: The name of the file to load the data.
|
|
:return: The salt and hash of the password.
|
|
"""
|
|
with open(filename, 'r') as file:
|
|
data = json.load(file)
|
|
return data['salt'], data['hashed_password']
|
|
|
|
def get_cost_factor():
|
|
"""
|
|
Prompts the user to enter a valid cost factor.
|
|
|
|
:return: The cost factor entered by the user.
|
|
"""
|
|
while True:
|
|
cost_factor_input = input("Enter the cost factor (default 12, typically between 4 and 31): ")
|
|
if cost_factor_input == '':
|
|
return 12 # Use the default value if the user enters nothing
|
|
try:
|
|
cost_factor = int(cost_factor_input)
|
|
if 4 <= cost_factor <= 31:
|
|
return cost_factor
|
|
else:
|
|
print("The cost factor must be between 4 and 31. Please try again.")
|
|
except ValueError:
|
|
print("Please enter a valid number.")
|
|
|
|
def main():
|
|
while True:
|
|
print("\nOptions:")
|
|
print("1. Enter a password and generate a hash.")
|
|
print("2. Verify the match between a hash and a password.")
|
|
print("3. Save the salt and hash to a file.")
|
|
print("4. Load the salt and hash from a file.")
|
|
print("5. Enter multiple passwords and generate hashes.")
|
|
print("6. Quit.")
|
|
|
|
choice = input("Choose an option (1/2/3/4/5/6): ")
|
|
|
|
if choice == '1':
|
|
password = input("Enter the password: ")
|
|
cost_factor = get_cost_factor()
|
|
salt = generate_salt(cost_factor)
|
|
hashed_password = hash_password(password, salt)
|
|
print(f"Salt: {salt}")
|
|
print(f"Password hash: {hashed_password}")
|
|
|
|
elif choice == '2':
|
|
try:
|
|
hashed_password = input("Enter the password hash: ")
|
|
password_to_verify = input("Enter the password to verify: ")
|
|
match = verify_password(hashed_password, password_to_verify)
|
|
print(f"Does the password match the hash? {match}")
|
|
except Exception as e:
|
|
print(f"Error verifying the password: {e}")
|
|
|
|
elif choice == '3':
|
|
try:
|
|
salt = input("Enter the salt: ")
|
|
hashed_password = input("Enter the password hash: ")
|
|
filename = input("Enter the filename to save the data: ")
|
|
save_to_file(salt, hashed_password, filename)
|
|
print(f"Data saved to {filename}")
|
|
except Exception as e:
|
|
print(f"Error saving the data: {e}")
|
|
|
|
elif choice == '4':
|
|
try:
|
|
filename = input("Enter the filename to load the data: ")
|
|
salt, hashed_password = load_from_file(filename)
|
|
print(f"Salt: {salt}")
|
|
print(f"Password hash: {hashed_password}")
|
|
except Exception as e:
|
|
print(f"Error loading the data: {e}")
|
|
|
|
elif choice == '5':
|
|
cost_factor = get_cost_factor()
|
|
while True:
|
|
password = input("Enter the password (or type 'quit' to stop): ")
|
|
if password.lower() == 'quit':
|
|
break
|
|
salt = generate_salt(cost_factor)
|
|
hashed_password = hash_password(password, salt)
|
|
print(f"Salt: {salt}")
|
|
print(f"Password hash: {hashed_password}")
|
|
|
|
elif choice == '6':
|
|
print("Goodbye!")
|
|
break
|
|
|
|
else:
|
|
print("Invalid option. Please choose a valid option.")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
|
|
|