Skip to main content

Password Validation

Aim

This library aims to allow the programmer to simply validate passwords according to their desired policy.

Flow

How does it work:

  • You create password policy
  • You test passwords against that policy
  • The passwords that abide by the policy are valid, those that don't abide are invalid

Simple.

Password Guidelines

I recommend reading the 2017 NIST guidelines:

  • Verifiers should not impose composition rules e.g., requiring mixtures of different character types or prohibiting consecutively repeated characters
  • Verifiers should not require passwords to be changed arbitrarily or regularly e.g. the previous 90 day rule
  • Passwords must be at least 8 characters in length
  • Password systems should permit subscriber-chosen passwords at least 64 characters in length.
  • All printing ASCII characters, the space character, and Unicode characters should be acceptable in passwords
  • When establishing or changing passwords, the verifier shall advise the subscriber that they need to select a different password if they have chosen a weak or compromised password
  • Verifiers should offer guidance such as a password-strength meter, to assist the user in choosing a strong password
  • Verifiers shall store passwords in a form that is resistant to offline attacks. Passwords shall be salted and hashed using a suitable one-way key derivation function. Key derivation functions take a password, a salt, and a cost factor as inputs then generate a password hash. Their purpose is to make each password guessing trial by an attacker who has obtained a password hash file expensive and therefore the cost of a guessing attack high or prohibitive.

Personal headline points:

  • Don't enforce bizarre convention e.g. 1 lowercase, 1 uppercase, 1 number, 1 symbol, etc
  • Don't make make users change them regularly
  • Make it at least 12 characters long
  • AND SALT AND HASH THEM WHEN PERSISTING

The XKCD comic puts it best: https://xkcd.com/936/

How to use

Install

Install it:

pip install password_validation

How

Example:

>>> from password_validation import PasswordPolicy
>>> policy = PasswordPolicy()
>>> policy.validate("hello-this-is-quite-a-good-password")
True

>>> policy.validate("password")
False

>>> test = policy.test_password("hello")
>>> test
[<RequirementUnfulfilled('the minimum password length', statement=(5 >= 12))>,
 <RequirementUnfulfilled('entropy', statement=(23.50219859070546 >= 32))>]

In the above example "password" is not valid, because it's not more than 12 characters (which is a default requirement). And "hello" isn't valid either because it's too short and too low in entropy.

You can, when using test_password get back a list of unfulfilled requirements.

Or you can see all the requirements:

>>> from password_validation import PasswordPolicy
>>> policy = PasswordPolicy()
>>> policy.test_password("goodbye", failure_only=False)
[<RequirementFulfilled('the minimum number of lowercase characters', statement=(7 >= 0))>,
 <RequirementFulfilled('the minimum number of uppercase characters', statement=(0 >= 0))>,
 <RequirementFulfilled('the minimum number of number characters', statement=(0 >= 0))>,
 <RequirementFulfilled('the minimum number of symbol characters', statement=(0 >= 0))>,
 <RequirementFulfilled('the minimum number of whitespace characters', statement=(0 >= 0))>,
 <RequirementFulfilled('the minimum number of other characters', statement=(0 >= 0))>,
 <RequirementUnfulfilled('the minimum password length', statement=(7 >= 12))>,
 <RequirementFulfilled('the maximum password length', statement=(7 <= 128))>,
 <RequirementFulfilled('entropy', statement=(32.90307802698764 >= 32))>,
 <RequirementFulfilled('forbidden words', statement=("goodbye" not in []))>]

The __init__ looks something like this:

class PasswordPolicy:
    def __init__(
        self,
        lowercase: int = 0,
        uppercase: int = 0,
        symbols: int = 0,
        numbers: int = 0,
        whitespace: int = 0,
        other: int = 0,
        min_length: int = 12,
        max_length: int = 128,
        entropy: typing.Union[int, float] = 32,
        forbidden_words: list = None
    )

Features in your policy can include:

  • number of lowercase characters (default 0) PasswordPolicy(lowercase=1)
  • number of uppercase characters (default 0) PasswordPolicy(uppercase=1)
  • number of symbols characters (default 0) PasswordPolicy(symbols=1)
  • number of number characters (default 0) PasswordPolicy(numbers=1)
  • number of whitespace characters (default 0) PasswordPolicy(whitespace=1)
  • number of other characters (default 0) PasswordPolicy(other=1)
  • minimum password length (default 12) PasswordPolicy(min_length=1)
  • maximum password length (default 128)PasswordPolicy(max_length=1)
  • minimum password entropy (default 32) PasswordPolicy(entropy=1)
  • a list of forbidden words PasswordPolicy(forbidden_words=['password'])

FYI other characters is if you wanted to add non-ascii characters

Flask example

from password_validation import PasswordPolicy

policy = PasswordPolicy()

@app.route("/register")
def register():
    password = request.form.get("password")
    if policy.validate(password):
        # create user
    else:
        for requirement in policy.test_password(password):
            alert = f"{requirement.name} not satisfied: expected: {requirement.requirement}, got: {requirement.actual}"
            flash(alert)
    return render_template("register.html")    

You can also get your fields using policy.to_dict()

Character Pool

If you don't like the default characters (ascii) you can make your own CharacterPool:

hex_pool = CharacterPool(
    lowercase="",
    uppercase="ABCDEF",
    numbers="0123456789",
    symbols="",
    whitespace="",
    other="",
)

or

random_pool = CharacterPool(
    lowercase="åéîøü",
    uppercase="XYZ",
    numbers="123",
    symbols=".",
    whitespace="",
    other="",
)

You can then pass to the policy:

policy = PasswordPolicy(character_pool=hex_pool)

and the same logic will apply but for that pool

Metadata

Release files for Password-Validation 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for Password-Validation 0.1.1
File Size Uploaded Provenance
Password Validation-0.1.1.tar.gz 11.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for Password-Validation 0.1.1
File Interpreter ABI Platform
Password_Validation-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 23.4 kB

Release files / Password Validation-0.1.1.tar.gz

Download URL Password Validation-0.1.1.tar.gz
Size 11.4 kB
Tags Source
SHA-256 checksum
How to use checksums
9c23c742230acc7fb54a063a709a848f35eff314656a27e7ca104fe7befb2eeb
BLAKE2b-256 checksum
How to use checksums
6032693f45dc1ef070d6126ebd99fc45fa8500955ebed9d7ad682414c49ec4d5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/49.2.1 requests-toolbelt/0.9.1 tqdm/4.48.2 CPython/3.6.4

Release files / Password_Validation-0.1.1-py3-none-any.whl

Download URL Password_Validation-0.1.1-py3-none-any.whl
Size 12.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b03904ff2a58e66b7902b60a21161b0b328fef3d75b330f50f58fa979ac2b234
BLAKE2b-256 checksum
How to use checksums
4d32df062a16f90f0af5742979e656083004170d4911fea96ccef9a2d9bddc83
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.2.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/49.2.1 requests-toolbelt/0.9.1 tqdm/4.48.2 CPython/3.6.4

Security for Password-Validation 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page