Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Alternative Bitwarden importer for Firefox Lockwise passwords, keeps everything into a separate folder
#!/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