mirror of https://github.com/wg-easy/wg-easy
committed by
GitHub
1 changed files with 147 additions and 0 deletions
@ -0,0 +1,147 @@ |
|||||
|
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() |
||||
|
|
Loading…
Reference in new issue