ulif / diceware

Passphrases to remember
GNU General Public License v3.0
353 stars 47 forks source link

Check generated passphrases againsts list of leaked passwords. #59

Open RatanShreshtha opened 5 years ago

RatanShreshtha commented 5 years ago

It would be nice to have the option to check generated passphrases against the list of leaked passwords from sources like Pwned Passwords which contains list of more than half a billion passwords which have previously been exposed in data breaches.

Pwned Passwords also implements a k-Anonymity model that allows a password to be searched for by partial hash.

If the user opts for checking the passphrases against the Pwned Passwords and it is found in the list then a new password should be generated for the user. This issue is inspired by the a Computerphile video.

Gooseus commented 5 years ago

Hey, just jumping in here for a hot second, though if I have time I may contribute to this project since I've been messing with Diceware CLI solutions myself on and off for a few years (I have a Nim implementation which compiles to C and then to a binary)

I think that this could be addressed with a little bit of clever documentation since it's my understanding (tbh, I haven't used this project yet) that the output is just the password and can thus be piped to another command.

https://medium.com/@monliclican/bash-one-liner-to-check-your-password-s-via-pwnedpasswords-coms-api-using-the-k-anonymity-method-a5807a9a8056

This article discusses the method you're talking about and offers a way to use a command line one-liner to check a password against the password.

Someone with a little bit more *nix-foo than I possess could probably adapt that to a one-liner that outputs the passphrase while also piping the output of the diceware command into a curl to that API. If that was added that to the documentation then you could avoid adding it as bloat to the actual script.

I only say bloat because I would bet $100 that if that 1M diceware passphrases were generated and tested against the Pwned Passwords API that you would have 0 hits.

drebs commented 2 years ago

In case it helps, here's a little Python3 script that'll check a string against the haveibeenpwned API (couldn't attach because GitHub doesn't accept .py):

#!/usr/bin/python3

import hashlib
import requests

class PwnedPassphraseException(Exception):
    pass

def check_pwned(passphrase):
    '''
    Check passphrase against the pwnedpasswords API.
    '''
    h = hashlib.sha1(passphrase.encode()).hexdigest().upper()
    response = requests.get(f'https://api.pwnedpasswords.com/range/{h[0:5]}')
    pwned = map(lambda i: i.split(':'), response.text.split())
    mypwn = [i for i in filter(lambda e: e[0] == h[5:], pwned)]
    if len(mypwn) == 1:
        n = mypwn[0][1]
        raise PwnedPassphraseException(n)

if __name__ == '__main__':
    import argparse
    import sys

    parser = argparse.ArgumentParser(description='Check if your passphrase is listed in the haveibeenpwned.com dataset.')
    parser.add_argument('passphrase')
    parser.add_argument('-q', '--quiet', action='store_true', help='Do not print a joyful message.')
    args = parser.parse_args()

    try:
        check_pwned(args.passphrase)
        if not args.quiet:
            print('Congrats! This passphrase has not been pwned (yet).')
    except PwnedPassphraseException as e:
        if not args.quiet:
            print(f'Oh, no! This passphrase appears {e.args[0]} times in the haveibeenpwned.com dataset.')
        sys.exit(1)