fesoliveira014 / PwnedPy

Check passwords using haveibeenpwned's k-Anonymity feature

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

PwnedPy

A simple python script and library that uses the haveibeenpwned APIv2 to check if a password or password hash has been pwned using k-Anonymity.

How it works

This module implements the range query from the haveibeenpwned APIv2, which uses k-Anonymity to better secure the hash you are requesting results for.

It works like this: Only the first 5 characters from the SHA-1 hash is sent to the server. The server then responds with hashes that matches the prefix. The hashes the server send back all have the first 5 chars cut away. The hashes are then assembled using the prefix and suffix, locally, to check if the password matches the one you provided.

You can read the blog post on this by the site's developer, here

Is it secure?

1Password has implemented this in their service, so go make up your own opinion. You should of course always be skeptical of where you punch in your password. You should also read the source code.

CLI Usage

$ python3 ./main.py --help
usage: main.py [-h] [--password PWD] [--hash PWDHASH]

Check if a password has been pwned using the haveibeenpwned APIv2.

optional arguments:
  -h, --help            show this help message and exit
  --password PWD, -p PWD
                        Password to check, in cleartext.
  --hash PWDHASH        Password to check, as a SHA-1 hash.

Example Usage

$ python3 ./main.py
Password:
$ python3 ./main.py --password "test"
$ python3 ./main.py --password test
$ python3 ./main.py --p "test"
$ python3 ./main.py --hash a94a8fe5ccb19ba61c4c0873d391e987982fbbd3

All of the above will give this result:

There was a match, go change your password!
Seen # times in the database: 68340

If there was no match found:

No match.

Using the module

Import the Pwned class.

from pwnedpy import Pwned, RateLimitException

Use the functions check and check_hash.

Both check and check_hash return the full hash and the number of time the password has been seen in the database, if it was a match.

h, count = p.check(pwd)

If there was no match, the functions return None and 0, respectively.

Example usage (from main.py)

(...)
args = parser.parse_args()
p = Pwned()
try:
    if not args.pwd and not args.pwdhash:
        pwd = getpass.getpass("Password: ")
        h, count = p.check(pwd)

    elif args.pwd:
        h, count = p.check(args.pwd)

    elif args.pwdhash:
        h, count = p.check_hash(args.pwdhash)

    if h:
        print("There was a match, go change your password!")
        print("Seen # times in the database: {}".format(count))
    else:
        print("No match.")

except RateLimitException as e:
    print("You're being rate-limited.")
except Exception as e:
    print("Error: {}".format(e))

TODOs

  • Implement the rest of the REST APIv2

Requirements

The script has only been tested with Python 3.6.4, it should work down to Python 3.4.x.

requests is the only other requirement. Install with pip install -r Requirements.txt, or pip install requests.

License

The code is licensed under an MIT license.

About

Check passwords using haveibeenpwned's k-Anonymity feature

License:MIT License


Languages

Language:Python 100.0%