Skip to content

Instantly share code, notes, and snippets.

@Tenzer
Last active July 16, 2024 10:19
Show Gist options
  • Save Tenzer/b8aa3cfa09a7e1396a0661de6bf35633 to your computer and use it in GitHub Desktop.
Save Tenzer/b8aa3cfa09a7e1396a0661de6bf35633 to your computer and use it in GitHub Desktop.
LastPass Pwned Passwords checker

LastPass Pwned Passwords checker

This is a script for checking if any of the passwords you have stored in LastPass have been exposed through previous data breaches.

To use the script you need to have Python 3 installed and you need a CSV export of your LastPass vault. The export can be generated from the LastPass CLI with:

lpass export > lastpass.csv

or can be extracted with the browser plugin by going to the LastPass icon → More Options → Advanced → Export → LastPass CSV File (note that I did have problems getting this to work).

You can then run the above script on the file with:

python3 check-passwords.py lastpass.csv

or you can feed the passwords directly into the script from the LastPass CLI without writing them to disk by sending them to standard input:

lpass export | python3 check-passwords.py

Due to how the Pwned Passwords API works, the actual passwords will never leave your computer. A SHA1 checksum of the passwords will be generated and only the first 5 characters of that checksum will be sent to the API.

The script will print a line for each password found to be compromised along with the name of the site as saved in the vault along with the number of times the password has occurred in data breaches.

#!/usr/bin/env python3
import csv
import fileinput
from functools import lru_cache
from hashlib import sha1
from urllib.request import Request, urlopen
def get_credentials():
with fileinput.input() as csvfile:
for credential in csv.DictReader(csvfile, delimiter=',', quotechar='"'):
if credential.get('password'):
yield credential
def get_hash(password):
checksum = sha1(password.encode()).hexdigest().upper()
return checksum[:5], checksum[5:]
@lru_cache(maxsize=4096)
def get_range(prefix):
request = Request('https://api.pwnedpasswords.com/range/{}'.format(prefix))
request.add_header('User-Agent', 'tenzers-pwned-passwords-checker (+https://gist.github.com/Tenzer/b8aa3cfa09a7e1396a0661de6bf35633)')
response = urlopen(request, timeout=10).read()
data = dict()
for line in response.decode().splitlines():
split_line = line.split(':')
data[split_line[0]] = split_line[1]
return data
def main():
for credential in get_credentials():
prefix, suffix = get_hash(credential['password'])
range_data = get_range(prefix)
if range_data.get(suffix):
print(
'{} occurrences found of the password for "{}"'.format(
range_data.get(suffix),
credential.get('name'),
)
)
if __name__ == '__main__':
main()
@Anguel
Copy link

Anguel commented Jan 18, 2019

Thank you very much! Export from LastPass via browser plugin worked for me, however LastPass gives you a .html file. You have to copy and paste it from browser to e.g. Notepad++ and save it as .csv. See also here:
https://lastpass.com/support.php?cmd=showfaq&id=1206

Another problem is that the file is in UTF-8 and your script does not use UTF-8. I worked around this by extending line 11 like this:

with fileinput.input(openhook=fileinput.hook_encoded("utf-8")) as csvfile:

I hope this helps :-)

@Fethbita
Copy link

One thing to consider is if you want to do this offline, it should still be possible. You could download the Pwned Passwords list and manually compare the hashes while you have your computer disconnected from the internet, which I think would be a safer option.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment