Created
August 25, 2021 17:12
-
-
Save melissaboiko/7d6d651a360c13995f5b9150381605af to your computer and use it in GitHub Desktop.
Alternative Bitwarden importer for Firefox Lockwise passwords, keeps everything into a separate folder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
'''lockwise2bitwarden.py: | |
Converts a Firefox Lockwise export CSV into a Bitwarden-format CSV. | |
Compared to using the built-in Firefox importer, this will: | |
- Save everything into a Lockwise-{timestamp} folder, and | |
- Save some extra Firefox stuff in the Notes field. | |
(Would be nice to use custom fields for those, but then we need | |
.json, and then we need to create folders, and then we need API | |
access...) | |
Usage: lockwise2bitwarden.py < from-firefox.csv > to-bitwarden.csv | |
Remember to import it using the Bitwarden importer, not the Firefox one! | |
''' | |
import sys | |
import csv | |
from datetime import datetime | |
import re | |
bitwarden_csv_columns=[ | |
'folder', | |
'favorite', | |
'type', | |
'name', | |
'notes', | |
'fields', | |
'reprompt', | |
'login_uri', | |
'login_username', | |
'login_password', | |
'login_totp', | |
] | |
lockwise_csv_columns=[ | |
'url', | |
'username', | |
'password', | |
'httpRealm', | |
'formActionOrigin', | |
'guid', | |
'timeCreated', | |
'timeLastUsed', | |
'timePasswordChanged', | |
] | |
def epoch2timestamp(epoch): | |
'''Firefox epoch (with milisecs) to timestamp string.''' | |
epoch = int(epoch) | |
epoch = round(epoch / 1000) | |
time = datetime.fromtimestamp(epoch) | |
return time.isoformat() | |
folder = 'Lockwise ' + datetime.now().strftime('%Y-%m-%dT%H:%M:%S') | |
reader = csv.DictReader(sys.stdin, delimiter=',', quotechar='"') | |
writer = csv.DictWriter(sys.stdout, bitwarden_csv_columns, delimiter=',', quotechar='"') | |
writer.writeheader() | |
for firefox in reader: | |
bitwarden={ | |
'folder': folder, | |
'favorite': '', | |
'type': 'login', | |
'fields': '', | |
'reprompt': '', | |
'login_totp': '', | |
} | |
domain=re.sub('https?://', '', firefox['url']) | |
domain=re.sub('/.*', '', domain) | |
bitwarden['name'] = firefox['username'] + '@' + domain | |
bitwarden['login_uri'] = firefox['url'] | |
bitwarden['login_username'] = firefox['username'] | |
bitwarden['login_password'] = firefox['password'] | |
timec = epoch2timestamp(firefox['timeCreated']) | |
timea = epoch2timestamp(firefox['timeLastUsed']) | |
timem = epoch2timestamp(firefox['timePasswordChanged']) | |
bitwarden['notes'] = "\n".join([ | |
f"http realm: {firefox['httpRealm']}", | |
f"form action origin: {firefox['formActionOrigin']}", | |
f"guid: {firefox['guid']}", | |
f"time created: {timec}", | |
f"time accessed: {timea}", | |
f"time modified: {timem}", | |
]) | |
writer.writerow(bitwarden) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment