CoolFace
Apppublic

vikrant892/password-strength-api

sourceHugging Faceupdated 1mo agoView on Hugging Face
0likes
generator.py58 linesDownload Raw Back to app
1import secrets
2import string
3
4# chars that look way too similar in most fonts
5AMBIGUOUS_CHARS = "0O1lI|`"
6
7
8def generate_password(
9    length: int = 16,
10    uppercase: bool = True,
11    lowercase: bool = True,
12    digits: bool = True,
13    symbols: bool = True,
14    exclude_ambiguous: bool = False,
15) -> str:
16    """
17    generate a cryptographically secure random password
18    uses secrets module (not random!) because random is not suitable for security
19    """
20    charset = ""
21
22    if lowercase:
23        charset += string.ascii_lowercase
24    if uppercase:
25        charset += string.ascii_uppercase
26    if digits:
27        charset += string.digits
28    if symbols:
29        charset += string.punctuation
30
31    if not charset:
32        # fallback if somehow everything is disabled (shouldn't happen with validation but just in case)
33        charset = string.ascii_letters + string.digits
34
35    if exclude_ambiguous:
36        charset = "".join(c for c in charset if c not in AMBIGUOUS_CHARS)
37
38    # generate and make sure we have at least one of each requested type
39    # otherwise you get complaints like "where's my number??"
40    while True:
41        password = "".join(secrets.choice(charset) for _ in range(length))
42
43        # verify at least one char from each requested category
44        checks = []
45        if lowercase:
46            checks.append(any(c in string.ascii_lowercase for c in password))
47        if uppercase:
48            checks.append(any(c in string.ascii_uppercase for c in password))
49        if digits:
50            checks.append(any(c in string.digits for c in password))
51        if symbols:
52            checks.append(any(c in string.punctuation for c in password))
53
54        if all(checks):
55            return password
56        # if we didn't get all categories, regenerate
57        # with length >= 8 this almost never loops more than once
58