Skip to main content

Pwned Passwords check (offline)

PyPI Code style: black

Features

  • Check passwords or plain SHA-1 hashes against haveibeenpwned password list
  • Fully offline operation, needs to be provided with external database file (~35 GB)
  • Optional Bloom filter to speed up common (negative) case

Quickstart

  • Download "SHA-1" version "(ordered by hash)" from https://haveibeenpwned.com/Passwords
  • Extract file, yielding pwned-passwords-sha1-ordered-by-hash-v8.txt (for current version 8), put into data directory under current directory
  • Install with pip install pwnedpasswords_offline
  • Optional: Seed Bloom filter: pwnedpasswords_offline_seed_bloom, takes about 45min to run, will generate a 512MiB file

Speed

(Results approximate, measured on my personal laptop)

w/o Bloom filter w/ Bloom filter
Positive match (pwned) 61 us/op 198 us/op
Negative match 121 us/op 14 us/op
Average @ 1% positive 64 us/op 16 us/op

These results were measured with batch operation at 20000 items. One-shot operation will be much slower due to the overhead of opening data files.

The data files are opened with mmap(2), and accessed in random order. No explicit non-garbage-collected Python objects are generated during operation, so it should be safe to open the data files once at the start of your application and then keep them open until your process ends. Note: The memory mapping will not survive a fork(2), so you cannot use a pre-forking webserver such as gunicorn to only open the data files once. Each process needs to open its own copy.

Simple usage

from pwnedpasswords_offline import PwnedPasswordsOfflineChecker
if PwnedPasswordsOfflineChecker("data/pwned-passwords-sha1-ordered-by-hash-v8.txt").lookup_raw_password("Password1!"):
    print("Pwned!")

Batch usage

You can also pre-open the database file, especially if you're checking multiple passwords in bulk:

from pwnedpasswords_offline import PwnedPasswordsOfflineChecker
checker = PwnedPasswordsOfflineChecker("data/pwned-passwords-sha1-ordered-by-hash-v8.txt")
checker.open()
for password in ["Password1!", "correct horse battery staple", "actress stapling driver placidly swivel doorknob"]:
    if checker.lookup_raw_password(password):
        print(f"'{password}' is pwned!")
checker.close()

You should not forget to call .close() after you're done.

As context manager

You can use the object as a context manager to automatically open and close it:

from pwnedpasswords_offline import PwnedPasswordsOfflineChecker
with PwnedPasswordsOfflineChecker("data/pwned-passwords-sha1-ordered-by-hash-v8.txt") as checker:
    for password in ["Password1!", "correct horse battery staple", "actress stapling driver placidly swivel doorknob"]:
        if checker.lookup_raw_password(password):
            print(f"'{password}' is pwned!")

Check hash directly

Instead of calling .lookup_raw_password() you can call .lookup_hash() if you already have the plain SHA-1 hash:

from pwnedpasswords_offline import PwnedPasswordsOfflineChecker
if PwnedPasswordsOfflineChecker("data/pwned-passwords-sha1-ordered-by-hash-v8.txt").lookup_hash("32CA9FD4B3F319419F2EA6F883BF45686089498D"):
    print("Pwned!")

Metadata

Release files for pwnedpasswords-offline 1.2.0

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

Source distribution (sdist)

Source distribution for pwnedpasswords-offline 1.2.0
File Size Uploaded Provenance Actions
pwnedpasswords-offline-1.2.0.tar.gz 17.0 kB Without provenance Details for pwnedpasswords-offline-1.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pwnedpasswords-offline 1.2.0
File Interpreter ABI Platform Actions
pwnedpasswords_offline-1.2.0-py3-none-any.whl Python 3 none any Details for pwnedpasswords_offline-1.2.0-py3-none-any.whl

Total release size: 44.5 kB

Release files / pwnedpasswords-offline-1.2.0.tar.gz

Download URL pwnedpasswords-offline-1.2.0.tar.gz
Size 17.0 kB
Tags Source
SHA-256 checksum
How to use checksums
fa63ba0a8982a566512aea02b56dd55bb94d8440cab1ce00112728951a7633e4
BLAKE2b-256 checksum
How to use checksums
7017b8171f37952180779ba840491e85b015e788d0a35d2dd09af6676711667b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.7.1 importlib_metadata/4.10.1 pkginfo/1.8.2 requests/2.27.1 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.10

Release files / pwnedpasswords_offline-1.2.0-py3-none-any.whl

Download URL pwnedpasswords_offline-1.2.0-py3-none-any.whl
Size 27.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
177013e60d26aa7ebd465b949a47073113ea1116112428092b1a433d4e963f9d
BLAKE2b-256 checksum
How to use checksums
53f2c3289938d16843b688a7adb0937a4886a8f385782abe7a3fed2fb0701471
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.7.1 importlib_metadata/4.10.1 pkginfo/1.8.2 requests/2.27.1 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.9.10

Security for pwnedpasswords-offline 1.2.0

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.

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