first commit

This commit is contained in:
Ivann LARUELLE 2024-01-29 01:39:20 +01:00
commit 9bc37aeae8
3 changed files with 186 additions and 0 deletions

12
Pipfile Normal file
View File

@ -0,0 +1,12 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
pyperclip = "*"
[dev-packages]
[requires]
python_version = "3.12"

28
Pipfile.lock generated Normal file
View File

@ -0,0 +1,28 @@
{
"_meta": {
"hash": {
"sha256": "8ceead135ee6991bd49b68802a159c7b7d7cfe2f2218d7a71d7a5d55b1d4cd6e"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.12"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"pyperclip": {
"hashes": [
"sha256:105254a8b04934f0bc84e9c24eb360a591aaf6535c9def5f29d92af107a9bf57"
],
"index": "pypi",
"version": "==1.8.2"
}
},
"develop": {}
}

146
main.py Normal file
View File

@ -0,0 +1,146 @@
import tkinter as tk
from tkinter import ttk
import random
import json
import pyperclip
from tkinter import messagebox
from tkinter import filedialog
# Constants for password characters
UPPERCASE_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
LOWERCASE_CHARS = 'abcdefghijklmnopqrstuvwxyz'
DIGITS = '0123456789'
SPECIAL_CHARS = '!@#$%^&*()-_=+[]{}|;:",.<>?/~'
AMBIGUOUS_CHARS = 'lI1oO0'
class PasswordGeneratorApp:
def __init__(self, root):
self.root = root
self.root.title("Password Generator")
# Variables for password generation
self.include_uppercase = tk.BooleanVar(value=True)
self.include_lowercase = tk.BooleanVar(value=True)
self.include_digits = tk.BooleanVar(value=True)
self.include_special = tk.BooleanVar(value=True)
self.exclude_ambiguous = tk.BooleanVar(value=False)
self.include_every_category = tk.BooleanVar(value=False)
self.password_length = tk.IntVar(value=12)
# Configure the main grid
self.root.columnconfigure(0, weight=1)
# Create and place widgets
self.create_widgets()
def create_widgets(self):
# Password entry
self.password_entry = ttk.Entry(self.root, font=('Arial', 14), width=40)
self.password_entry.grid(row=0, column=0, padx=10, pady=10, sticky="ew")
# Password settings frame
settings_frame = ttk.LabelFrame(self.root, text="Settings", padding=10)
settings_frame.grid(row=1, column=0, padx=10, pady=10, sticky="ew")
# Character type checkboxes
ttk.Checkbutton(settings_frame, text="A-Z", variable=self.include_uppercase, command=self.update_password).grid(row=0, column=0, sticky="w")
ttk.Checkbutton(settings_frame, text="a-z", variable=self.include_lowercase, command=self.update_password).grid(row=0, column=1, sticky="w")
ttk.Checkbutton(settings_frame, text="0-9", variable=self.include_digits, command=self.update_password).grid(row=0, column=2, sticky="w")
ttk.Checkbutton(settings_frame, text="Special", variable=self.include_special, command=self.update_password).grid(row=0, column=3, sticky="w")
ttk.Checkbutton(settings_frame, text="Exclude look-alike (lI1oO0)", variable=self.exclude_ambiguous, command=self.update_password).grid(row=1, column=0, columnspan=2, sticky="w")
ttk.Checkbutton(settings_frame, text="Include every category", variable=self.include_every_category, command=self.update_password).grid(row=1, column=2, columnspan=2, sticky="w")
# Password length slider
ttk.Label(settings_frame, text="Password Length:").grid(row=2, column=0, columnspan=2, sticky="w")
self.length_slider = ttk.Scale(settings_frame, from_=4, to_=32, orient='horizontal', variable=self.password_length, command=lambda event: self.update_password())
self.length_slider.grid(row=2, column=2, columnspan=2, sticky="ew")
# Buttons
button_frame = ttk.Frame(self.root)
button_frame.grid(row=2, column=0, padx=10, pady=10, sticky="ew")
button_frame.columnconfigure((0, 1, 2), weight=1)
ttk.Button(button_frame, text="Copy", command=self.copy_to_clipboard).grid(row=0, column=0, padx=5, pady=5, sticky="ew")
ttk.Button(button_frame, text="Save Settings", command=self.save_settings).grid(row=0, column=1, padx=5, pady=5, sticky="ew")
ttk.Button(button_frame, text="Load Settings", command=self.load_settings).grid(row=0, column=2, padx=5, pady=5, sticky="ew")
# Initial password generation
self.update_password()
def generate_password(self):
# Collect selected character types
chars = ''
if self.include_uppercase.get():
chars += UPPERCASE_CHARS
if self.include_lowercase.get():
chars += LOWERCASE_CHARS
if self.include_digits.get():
chars += DIGITS
if self.include_special.get():
chars += SPECIAL_CHARS
if self.exclude_ambiguous.get():
chars = ''.join(filter(lambda x: x not in AMBIGUOUS_CHARS, chars))
# Ensure the password includes at least one character from each selected category if required
password = ''
if self.include_every_category.get():
if self.include_uppercase.get():
password += random.choice(UPPERCASE_CHARS)
if self.include_lowercase.get():
password += random.choice(LOWERCASE_CHARS)
if self.include_digits.get():
password += random.choice(DIGITS)
if self.include_special.get():
password += random.choice(SPECIAL_CHARS)
random_chars = [random.choice(chars) for _ in range(self.password_length.get() - len(password))]
password += ''.join(random_chars)
else:
password = ''.join(random.choice(chars) for _ in range(self.password_length.get()))
return ''.join(random.sample(password, len(password)))
def update_password(self):
new_password = self.generate_password()
self.password_entry.delete(0, tk.END)
self.password_entry.insert(0, new_password)
def copy_to_clipboard(self):
password = self.password_entry.get()
pyperclip.copy(password)
messagebox.showinfo("Password Generator", "Password copied to clipboard!")
def save_settings(self):
settings = {
'include_uppercase': self.include_uppercase.get(),
'include_lowercase': self.include_lowercase.get(),
'include_digits': self.include_digits.get(),
'include_special': self.include_special.get(),
'exclude_ambiguous': self.exclude_ambiguous.get(),
'include_every_category': self.include_every_category.get(),
'password_length': self.password_length.get()
}
filename = filedialog.asksaveasfilename(defaultextension='.json', filetypes=[("JSON files", "*.json")])
if filename:
with open(filename, 'w') as f:
json.dump(settings, f)
messagebox.showinfo("Password Generator", "Settings saved successfully!")
def load_settings(self):
filename = filedialog.askopenfilename(filetypes=[("JSON files", "*.json")])
if filename:
with open(filename, 'r') as f:
settings = json.load(f)
self.include_uppercase.set(settings['include_uppercase'])
self.include_lowercase.set(settings['include_lowercase'])
self.include_digits.set(settings['include_digits'])
self.include_special.set(settings['include_special'])
self.exclude_ambiguous.set(settings['exclude_ambiguous'])
self.include_every_category.set(settings['include_every_category'])
self.password_length.set(settings['password_length'])
self.update_password()
messagebox.showinfo("Password Generator", "Settings loaded successfully!")
if __name__ == "__main__":
root = tk.Tk()
app = PasswordGeneratorApp(root)
root.mainloop()