Skip to main content
import secrets
PASSWORD_LENGTH = 10

def _generate(_what_to_generate_from : list[str] | str):
    """Generate random characters based on the list given

    Args:
        _what_to_generate_from (list[str]): The list of characters
    
    Raises:
        ValueError : If the argument is not an iterable of strings

    Returns:
        str : The generated password.

    ----- This Functions Is not for prior use , It is only be used in generate_random_password function.
    """

    password =return ''.join(secrets.choice(_what_to_generate_from) for i in range(PASSWORD_LENGTH)
    return password
)
import secrets
PASSWORD_LENGTH = 10

def _generate(_what_to_generate_from : list[str] | str):
    """Generate random characters based on the list given

    Args:
        _what_to_generate_from (list[str]): The list of characters
    
    Raises:
        ValueError : If the argument is not an iterable of strings

    Returns:
        str : The generated password.

    ----- This Functions Is not for prior use , It is only be used in generate_random_password function.
    """

    password = ''.join(secrets.choice(_what_to_generate_from) for i in range(PASSWORD_LENGTH)
    return password

import secrets
PASSWORD_LENGTH = 10

def _generate(_what_to_generate_from : list[str] | str):
    """Generate random characters based on the list given

    Args:
        _what_to_generate_from (list[str]): The list of characters
    
    Raises:
        ValueError : If the argument is not an iterable of strings

    Returns:
        str : The generated password.

    ----- This Functions Is not for prior use , It is only be used in generate_random_password function.
    """

    return ''.join(secrets.choice(_what_to_generate_from) for i in range(PASSWORD_LENGTH))
Performance, and grammar
Source Link

The biggest red flag that I see is using random to generate passwords. This is warned against in the python docs on random, which have examples for various usecases, such as token generation.

Warning: The pseudo-random generators of this module should not be used for security purposes. For security or cryptographic uses, see the secrets module, which has examples for various usecases, such as token generation.

Perfomance

This is another topic of concern, because from reading the code below

_first_random_number = randint(0,len(_what_to_generate_from) - 1)
_second_random_number = randint(0, len(_what_to_generate_from) - 1)
    if _first_random_number == _second_random_number:

It becomes clear that you have an algorithmic complexity problem. What is that? Well, if you supply a big enough character list, the password generator can be used in a Denial-of-Service attack. Here's the gist: It you have a 5-long character list, your inner-loop has 1-in-25 chance of actually adding a character. This means it should take about 250 iterations to generate a password of length 10. If you have an 80 character list, it will take... 64,000 times. And if you have 128....163,840 times. This is in effect, DOS.

The biggest red flag that I see is using random to generate passwords. This is warned against in the python docs on random, which have examples for various usecases, such as token generation.

Warning: The pseudo-random generators of this module should not be used for security purposes. For security or cryptographic uses, see the secrets module.

The biggest red flag that I see is using random to generate passwords. This is warned against in the python docs on random.

Warning: The pseudo-random generators of this module should not be used for security purposes. For security or cryptographic uses, see the secrets module, which has examples for various usecases, such as token generation.

Perfomance

This is another topic of concern, because from reading the code below

_first_random_number = randint(0,len(_what_to_generate_from) - 1)
_second_random_number = randint(0, len(_what_to_generate_from) - 1)
    if _first_random_number == _second_random_number:

It becomes clear that you have an algorithmic complexity problem. What is that? Well, if you supply a big enough character list, the password generator can be used in a Denial-of-Service attack. Here's the gist: It you have a 5-long character list, your inner-loop has 1-in-25 chance of actually adding a character. This means it should take about 250 iterations to generate a password of length 10. If you have an 80 character list, it will take... 64,000 times. And if you have 128....163,840 times. This is in effect, DOS.

Source Link

Security

The biggest red flag that I see is using random to generate passwords. This is warned against in the python docs on random, which have examples for various usecases, such as token generation.

Warning: The pseudo-random generators of this module should not be used for security purposes. For security or cryptographic uses, see the secrets module.

Now, why should we not use random? The answer is, with 638 characters (or 62 passwords, plaintext), an attacker can get the seed of random, and predict all passwords to come, what order they will appear, and the security of your application/program disappears. (A bit simplified, i agree, but you should never use random for security purposes) Also, if you are generating passwords and storing them in plaintext, that becomes a much more serious security vulnerability than the above. Please, follow the advice given atcwe.mitre.org

Bandit

If you are writing security-minded applications, or even want more security, I seriously recommend you use Bandit as a linter. Bandit can be run in vscode, as well as used as a linter by almost any modern IDE. Adding in the missing from random import randint, and running the code through py -m bandit code.txt

>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/blacklists/blacklist_calls.html#b311-random
   Location: bad.txt:25:31
24      while _counter < OperationalVariables.input_desired_length:
25          _first_random_number = randint(0,len(_what_to_generate_from) - 1)
26          _second_random_number = randint(0, len(_what_to_generate_from) - 1)

--------------------------------------------------
>> Issue: [B311:blacklist] Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   Severity: Low   Confidence: High
   CWE: CWE-330 (https://cwe.mitre.org/data/definitions/330.html)
   More Info: https://bandit.readthedocs.io/en/1.7.5/blacklists/blacklist_calls.html#b311-random
   Location: bad.txt:26:32
25          _first_random_number = randint(0,len(_what_to_generate_from) - 1)
26          _second_random_number = randint(0, len(_what_to_generate_from) - 1)
27  

--------------------------------------------------

Code scanned:
    Total lines of code: 25
    Total lines skipped (#nosec): 0

Run metrics:
    Total issues (by severity):
        Undefined: 0
        Low: 2
        Medium: 0
        High: 0
    Total issues (by confidence):
        Undefined: 0
        Low: 0
        Medium: 0
        High: 2
Files skipped (0):

Taking advantage of secrets, the function becomes much simpler, and secure

import secrets
PASSWORD_LENGTH = 10

def _generate(_what_to_generate_from : list[str] | str):
    """Generate random characters based on the list given

    Args:
        _what_to_generate_from (list[str]): The list of characters
    
    Raises:
        ValueError : If the argument is not an iterable of strings

    Returns:
        str : The generated password.

    ----- This Functions Is not for prior use , It is only be used in generate_random_password function.
    """

    password = ''.join(secrets.choice(_what_to_generate_from) for i in range(PASSWORD_LENGTH)
    return password