Last active
May 21, 2023 15:26
-
-
Save tarneaux/08b6abdda02a921ed9282660926cb3a5 to your computer and use it in GitHub Desktop.
Convert bitwarden CSV to GNU passwordstore
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 | |
# Convert Bitwarden CSV export to pass format | |
import pandas | |
import os | |
import sys | |
import subprocess | |
# Check for correct number of arguments | |
if len(sys.argv) != 2: | |
print("Usage: bitwarden_to_pass.py <bitwarden_export.csv>") | |
sys.exit(1) | |
# Read CSV file | |
with open(sys.argv[1], newline='') as csvfile: | |
df = pandas.read_csv(csvfile) | |
# For each row, run pass add | |
def get_formatted_info_from_row(row): | |
# Example from pass: | |
# aAtkJ12K | |
# URL: *.amazon.com/* | |
# Username: [email protected] | |
# Secret Question 1: What is your childhood best friend's most bizarre superhero fantasy? Oh god, Amazon, it's too awful to say... | |
# Phone Support PIN #: 84719 | |
# We will also name the file {folder}/{name} or just {name} if there is no folder | |
# bitwarden CSV columns: | |
# folder,favorite,type,name,notes,fields,reprompt,login_uri,login_username,login_password,login_totp | |
# NAME | |
if not pandas.isnull(row.loc['folder']): | |
# Get the folder name | |
name = row['folder'] + "/" | |
else: | |
name = "" | |
name += row['name'] | |
contents = f"{row['login_password']}\n" | |
contents += f"URL: {row['login_uri']}\n" | |
contents += f"Username: {row['login_username']}\n" | |
contents += f"Notes: {row['notes']}\n" | |
contents += f"TOTP: {row['login_totp']}\n" | |
contents += f"Fields: {row['fields']}\n" | |
return name, contents | |
for index, row in df.iterrows(): | |
name, contents = get_formatted_info_from_row(row) | |
print(f"Adding {name}...") | |
# Run pass add | |
subprocess.run(["pass", "insert", "-m", name], input=contents, encoding='ascii', check=True, stdout=subprocess.DEVNULL) | |
print("Done!") | |
print(f"Now, you DO NOT want to run 'rm {sys.argv[1]}'.") | |
print(f"Before removing a sensitive file like this, you should always run 'shred {sys.argv[1]}'.") | |
print("This will overwrite the file with random data before deleting it.") | |
print("This is important because otherwise, the data will still be on your hard drive and is recoverable with tools like TestDisk.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment