Reusing Passwords

I have a confession. Sometimes I reuse passwords. Not for anything that “matters”, but I’ve ended up using a couple of passwords a lot of times. And inevitably some of those sites get hacked. But where did I use them?

Chrome remembers all my passwords but unfortunately doesn’t seem to offer a straightforward API to get at them. Conveniently they do sync my passwords to my computer’s password store and there’s an API for that.

I wrote a little script and I’ve been going through generating unique passwords for all the unimportant sites and turning two-factor authentication on where it’s offered. The Secret Service database (and Chrome) seem to sometimes end up with multiple entries for a single site, and Chrome doesn’t seem to sync my updates immediately, but I’ve found this a helpful start.

#!/usr/bin/env python3
import argparse
import sys
import datetime
import secretstorage
import functools
def datetime_from_ss(ts):
datetime.datetime.fromtimestamp(int(ts) / 10000000)
class StoredPassword:
def __init__(self, item):
self.item = item
self.url = item.get_label()
self.password = item.get_secret().decode()
attributes = item.get_attributes()
self.realm = attributes['signon_realm']
self.username = attributes['username_value']
self.created = datetime_from_ss(attributes['date_created'])
self.synced = datetime_from_ss(attributes['date_synced'])
def __id__(self):
return id(self.item)
def __eq__(self, other):
return self.item == other.item
def __hash__(self):
return hash(self.item)
def __lt__(self, other):
return (self.created, self.synced) < (other.created, other.synced)
def __repr__(self):
date_format = '%Y-%m-%d'
return 'StoredPassword(%s %s %s %s %s)' % (
self.realm, self.username, self.password,
def get_all_passwords():
print('Loading passwords…')
bus = secretstorage.dbus_init()
collection = secretstorage.get_default_collection(bus)
return [StoredPassword(item)
for item in collection.get_all_items()
if item.get_attributes()['xdg:schema'] ==
def password_for_site_matching(pattern, all_passwords):
matching = [item for item in all_passwords if pattern in item.realm]
pws = set(m.password for m in matching)
if len(pws) > 1:
print('Found %d passwords across %d password manager entries:')
for m in matching:
print(' %s %s' % (m.username, m.url))
print('Use a more specific match.')
return pws.pop()
def find_matching_passwords(password, site_pattern, all_passwords):
reuse = [item
for item in all_passwords
if item.password == password and (site_pattern is None or site_pattern not in item.realm)]
reuse.sort(key=lambda pw: pw.realm)
if len(reuse):
print('Found password. It is reused across %d sites:' % len(reuse))
username_width = max(len(item.username) for item in reuse)
for item in reuse:
print('{:{width}} {}'.format(item.username,
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Find reused passwords')
help='Find sites reusing a the password from this site')
help='Find sites using this password')
args = parser.parse_args()
if not and not args.password:
if and args.password:
print('You can only pass one of –site and –password')
all_passwords = get_all_passwords()
password = password_for_site_matching(, all_passwords)
password = args.password
find_matching_passwords(password,, all_passwords)

view raw
hosted with ❤ by GitHub