Pwned Passwords check (offline)
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 intodatadirectory 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)
| 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)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| 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.