Skip to content

Instantly share code, notes, and snippets.

@roman-yepishev
Last active April 6, 2018 06:07
Show Gist options
  • Select an option

  • Save roman-yepishev/80737d1f595795073504 to your computer and use it in GitHub Desktop.

Select an option

Save roman-yepishev/80737d1f595795073504 to your computer and use it in GitHub Desktop.
Converts ZohoVault export to KeePassX .kdb (python 3 only)
#!/usr/bin/python3
"""Convert Zoho Vault Export CSV to KeePass KDB
Usage: zohovault2keepass.py ZohoVault.csv keepass.kdb
You will be prompted for the encryption password.
"""
import csv
import collections
import getpass
import sys
import kppy.database
EXPORT_GROUP = 'Zoho Vault'
ZohoVaultEntry = collections.namedtuple('ZohoVaultEntry', [
'secret_name', 'description', 'secret_url', 'secret_data',
'notes', 'custom_data', 'tags', 'classification', 'favorite',
'chamber_name'
])
class ZohoVaultConverter(object):
"""Zoho Vault Converter"""
def __init__(self):
"""Initialize converter"""
self._database = None
self._group = None
def _prepare_db(self, path, password):
"""Prepare KDB database and group"""
self._database = kppy.database.KPDBv1(
filepath=path, password=password, new=True
)
# This returns boolean, so we need to hunt for the group
self._database.create_group(title=EXPORT_GROUP)
for item in self._database.groups:
if item.title == EXPORT_GROUP:
self._group = item
break
if self._group is None:
raise RuntimeError("Created group is not found")
def convert(self, input_path, output_path, password):
"""Convert CSV-ish data exported from Zoho Vault to KDB"""
self._prepare_db(output_path, password)
entries = []
with open(input_path, 'r', encoding='utf-8') as filehandle:
reader = csv.reader(filehandle)
# fast-forward through the header
next(reader)
for row in [v for v in reader if v]:
entries.append(self._process_row(row))
for entry in entries:
entry["group"] = self._group
self._database.create_entry(**entry)
self._database.save()
self._database.close()
@staticmethod
def _process_row(row):
"""Process Vault Entry"""
if len(row) > 10:
assert row[10] == ''
entry = ZohoVaultEntry(*row[0:10])
secret_data = {}
for line in [v.strip() for v in entry.secret_data.split('\n')
if v != '']:
key, value = line.split(':', 1)
secret_data[key] = value
comment = []
if entry.description.strip() != '':
comment.append(entry.description)
if entry.notes.strip() != '':
comment.append(entry.notes)
if entry.custom_data.strip() != '':
comment.append(entry.custom_data)
return {
"title": entry.secret_name,
"url": entry.secret_url,
"username": secret_data.get("User Name", ''),
"password": secret_data.get("Password", ''),
"comment": '\n'.join(comment)
}
if __name__ == "__main__":
if len(sys.argv) != 3:
print(__doc__)
sys.exit(1)
converter = ZohoVaultConverter()
master_password = getpass.getpass()
converter.convert(
sys.argv[1],
sys.argv[2],
master_password
)
@deltagolf
Copy link
Copy Markdown

Hi there!
I've tried to use your script but it throws a persisten error all the time.

MacBook-Pro-**********$ python3 zohovault2keepass.py csv_zv.csv zoho-export.kdb
Password: 
Traceback (most recent call last):
  File "zohovault2keepass.py", line 121, in <module>
    master_password
  File "zohovault2keepass.py", line 66, in convert
    entries.append(self._process_row(row))
  File "zohovault2keepass.py", line 103, in _process_row
    "username": secret_data["User Name"],
KeyError: 'User Name'

I've just updated pip3 and python3, running on a Mac. Any ideas?

@roman-yepishev
Copy link
Copy Markdown
Author

You may not have a user name in one of the fields. Updated the gist to work with missing User Name or Password, however I did not prepare tests for this script, so YMMV.

@deltagolf
Copy link
Copy Markdown

Yup, that was it. You've nailed it. Thank you!

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