Skip to content

Instantly share code, notes, and snippets.

@ignlg
Forked from mpalet/bw_export_kp.py
Last active March 31, 2020 18:20
Show Gist options
  • Save ignlg/0a349712a973cb94be67c8c4a3e3a196 to your computer and use it in GitHub Desktop.
Save ignlg/0a349712a973cb94be67c8c4a3e3a196 to your computer and use it in GitHub Desktop.
Export Bitwarden to KeePass 2 XML format, with custom banned fields to clean things up
#!/usr/bin/python
from __future__ import print_function
import xmltodict
import json
import sys
import commands
import uuid
import base64
def get_uuid(name):
name = name.encode('ascii', 'ignore')
uid = uuid.uuid5(uuid.NAMESPACE_DNS, name)
return base64.b64encode(uid.bytes)
def get_folder(f):
return dict(UUID=get_uuid(f['name']),
Name=f['name'])
def get_protected_value(v):
return {'#text': v, '@ProtectInMemory': 'True'}
def get_entry(e):
fields = []
if 'fields' in e:
for f in e['fields']:
if f['name'] is not None:
fields.append(dict(Key=f['name'],
Value=get_protected_value(f['value'])))
urls = ''
username, password = '', ''
notes = e['notes'] if e['notes'] is not None else ''
if 'login' in e:
if 'uris' in e['login']:
urls = [u['uri'] for u in e['login']['uris']]
urls = ','.join(urls)
username = e['login']['username']
password = e['login']['password']
username = username or ''
password = password or ''
entry = dict(UUID=get_uuid(e['name']),
String=[dict(Key='Title', Value=e['name']),
dict(Key='UserName', Value=username),
dict(Key='Password', Value=get_protected_value(password)),
dict(Key='URL', Value=urls),
dict(Key='Notes', Value=notes)
] + fields)
# print(entry)
return entry
def main():
# get output from bw
cmd = "(bw list folders | jq '{folders: .}' ; bw list items | jq '{items: .}') | cat | jq -s '. | add'"
status, output = commands.getstatusoutput(cmd)
# read stdin
# stdin = sys.stdin.read()
if status != 0:
print("Error ...")
print(output)
sys.exit(1)
# parse input to json
d = json.loads(output)
#print(d['folders'][0]['name'])
# print(d['items'][0])
# print(get_entry(d['items'][0]))
entries = [get_entry(e) for e in d['items']]
# Meta element
meta = dict()
# loop over folders
in_folders = d['folders']
out_folders = []
for f in in_folders:
folder = get_folder(f)
folder_id = f['id']
# loop on entries in this folder
out_entries = []
for entry, item in zip(entries, d['items']):
if item['folderId'] == folder_id:
out_entries.append(entry)
# add if there is something
if len(out_entries) > 0:
folder['Entry'] = out_entries
# add to output
out_folders.append(folder)
# Root group
root_group = get_folder(dict(name='Root'))
root_group['Group'] = out_folders
# root_group['Entry'] = entries
# Root element
root=dict(Group=root_group)
# xml contents
xml = dict(KeePassFile=dict(Meta=meta, Root=root))
print(xmltodict.unparse(xml, pretty=True))
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment