| import gradio as gr |
| import string |
| import secrets |
| import math |
|
|
| SYMBOLS = "!@#$%^&*()-_=+[]{}|;:,.<>?/" |
|
|
| def analyze_password(length, pool_size): |
| entropy = length * math.log2(pool_size) |
|
|
| if entropy < 40: |
| strength = "Weak" |
| crack_time = "Seconds to Minutes" |
| elif entropy < 60: |
| strength = "Medium" |
| crack_time = "Hours to Days" |
| elif entropy < 80: |
| strength = "Strong" |
| crack_time = "Years" |
| elif entropy < 100: |
| strength = "Very Strong" |
| crack_time = "Millions of Years" |
| else: |
| strength = "Extremely Strong" |
| crack_time = "Practically Uncrackable" |
|
|
| return entropy, strength, crack_time |
|
|
|
|
| def generate_password(length, letters, numbers, symbols, allow_repeats): |
| try: |
| length = int(length) |
| except: |
| return "Error", "Length must be a valid number." |
|
|
| if length <= 0: |
| return "Error", "Length must be greater than 0." |
|
|
| pool = "" |
|
|
| if letters: |
| pool += string.ascii_letters |
|
|
| if numbers: |
| pool += string.digits |
|
|
| if symbols: |
| pool += SYMBOLS |
|
|
| if not pool: |
| return "Error", "Select at least one character type." |
|
|
| unique_chars = len(set(pool)) |
|
|
| if not allow_repeats and length > unique_chars: |
| selected = [] |
|
|
| if letters: |
| selected.append("Letters") |
|
|
| if numbers: |
| selected.append("Numbers") |
|
|
| if symbols: |
| selected.append("Symbols") |
|
|
| return ( |
| "Impossible Request", |
| f"You selected: {', '.join(selected)}\n" |
| f"Repeated characters disabled.\n\n" |
| f"Only {unique_chars} unique characters are available,\n" |
| f"but you requested {length} characters." |
| ) |
|
|
| if allow_repeats: |
| password = "".join( |
| secrets.choice(pool) |
| for _ in range(length) |
| ) |
| else: |
| password = "".join( |
| secrets.SystemRandom().sample(pool, length) |
| ) |
|
|
| entropy, strength, crack_time = analyze_password( |
| len(password), |
| len(set(pool)) |
| ) |
|
|
| analysis = ( |
| f"Strength: {strength}\n" |
| f"Entropy: {entropy:.1f} bits\n" |
| f"Estimated Crack Time: {crack_time}" |
| ) |
|
|
| return password, analysis |
|
|
|
|
| with gr.Blocks(title="Password Generator V2") as demo: |
| gr.Markdown("# 🔐 Password Generator V2") |
| gr.Markdown( |
| "Generate secure passwords and estimate their strength." |
| ) |
|
|
| length = gr.Number( |
| value=16, |
| label="Password Length", |
| minimum=1, |
| precision=0 |
| ) |
|
|
| with gr.Row(): |
| letters = gr.Checkbox( |
| value=True, |
| label="Letters (A-Z, a-z)" |
| ) |
|
|
| numbers = gr.Checkbox( |
| value=True, |
| label="Numbers (0-9)" |
| ) |
|
|
| symbols = gr.Checkbox( |
| value=False, |
| label="Symbols" |
| ) |
|
|
| allow_repeats = gr.Checkbox( |
| value=True, |
| label="Allow Repeated Characters" |
| ) |
|
|
| generate_btn = gr.Button("Generate Password") |
|
|
| password_output = gr.Textbox( |
| label="Generated Password", |
| lines=2 |
| ) |
|
|
| analysis_output = gr.Textbox( |
| label="Password Analysis", |
| lines=4 |
| ) |
|
|
| generate_btn.click( |
| fn=generate_password, |
| inputs=[ |
| length, |
| letters, |
| numbers, |
| symbols, |
| allow_repeats |
| ], |
| outputs=[ |
| password_output, |
| analysis_output |
| ] |
| ) |
|
|
| demo.launch() |