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