Skip to content

Instantly share code, notes, and snippets.

@simsor
Created June 27, 2017 17:21
Show Gist options
  • Save simsor/747e1065d051ce6d7417439110637aaa to your computer and use it in GitHub Desktop.
Save simsor/747e1065d051ce6d7417439110637aaa to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
# Convert your pass(1) password database to a Keepass 2 (.kdbx) database.
# Change the PASS_DIR, KP_FILE and PASSPHRASE variables
# Create the kdbx file beforehand. The script assumes the passphrase of your GPG key and the database password are the same.
# You'll need the pykeepass libraries (install with pip3) and gpg installed on your computer
# Make sure your pass key is in your GPG keyring, there's absolutely no checks whatsoever
# I've only tested this with the WSL on Windows 10, so yeah, YMMV
from pykeepass import PyKeePass
import subprocess
import os
import sys
PASS_DIR = "/mnt/c/Users/Simon/AppData/Roaming/password-store"
KP_FILE = "./database.kdbx"
PASSPHRASE = ""
contents = {}
kp = PyKeePass(KP_FILE, password=PASSPHRASE)
def gpg_decrypt(file, passphrase):
p = subprocess.Popen(["gpg", "--passphrase", passphrase, "--decrypt", file], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(out, _) = p.communicate()
return out
def unpass(dir, c):
for entry in os.listdir(dir):
if entry[0] == ".":
continue
fullpath = os.path.join(dir, entry)
if os.path.isdir(fullpath):
c[entry] = {}
unpass(fullpath, c[entry])
else:
if entry[-4:] == ".gpg":
entry = entry[:-4]
c[entry] = {}
c[entry]["ENTRYTYPE"] = "file"
decrypted = gpg_decrypt(fullpath, PASSPHRASE).decode("UTF-8")
parts = decrypted.split("\n")
c[entry]["password"] = parts[0]
c[entry]["username"] = ""
c[entry]["notes"] = ""
c[entry]["url"] = ""
for part_idx in range(1, len(parts)):
if not parts[part_idx]:
continue
label = parts[part_idx].split(":")[0]
info = ":".join(parts[part_idx].split(":")[1:])
info = info.lstrip(" ")
if label.lower() == "username":
c[entry]["username"] = info
elif label.lower() == "url":
c[entry]["url"] = info
else:
c[entry]["notes"] += label + ": " + info + "\n"
def tokeepass(curgroup, c):
for (k, v) in c.items():
if "ENTRYTYPE" in v and v["ENTRYTYPE"] == "file":
kp.add_entry(curgroup, k, v["username"], v["password"], url=v["url"], notes=v["notes"])
else:
g = kp.add_group(curgroup, k)
tokeepass(g, v)
def main():
pass_key = open(os.path.join(PASS_DIR, ".gpg-id")).read().strip()
print("Pass key:", pass_key)
print("====")
unpass(PASS_DIR, contents)
# Create base groups
for (k, v) in contents.items():
if "ENTRYTYPE" in v and v["ENTRYTYPE"] == "file":
continue
g = kp.add_group(kp.root_group, k)
tokeepass(g, v)
kp.save()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment