Moving from password-store to Bitwarden
Password-store, the one true unix way of password management has served me well for over 6 years. However, as I'm starting to use other devices in tandem such as my phone and laptop, I've become jealous of those who can easily fill in their credentials with a click of a button.
Right now, my workflow on my desktop and laptop computers (which run windows) are:
- open windows terminal, ssh into my server that holds my passwords
- run
pass - copy the output
- paste it where I need it
It's been very cumbersome, but the friction was low enough that I haven't done anything about it. However, it's time to make things a bit easier as this workflow has been feeling more cumbersome recently.
I had tried to make a nicer workflow for pass on
windows, but getting gpg running properly has been a
nightmare, and I eventually gave up. Further, passff
extension can't connect to the local instance of pass
properly and keeps complaining. I'm sure I could get it to work easily
on linux or *BSD, but here we are!
Exporting from password-store
As password-store deals with basic tools, exporting passwords is superbly easy. In fact, this is one of the main reasons I've stuck to it for so long, because I always knew my passwords were safe and in my control.
To do all this, I'm using linux under WSL on windows as I don't
want to deal with Windows's idiosyncrasies with gpg and
pass.
To export passwords from pass, gpg can be
used directly after importing your key and decrypting individual
files. The below snippet assumes you have your passwords in
passwd directory and want the decrypted files in
passwd-decrypted directory with the same directory
structure. First, we copy the directory as is, deleting all the gpg
files inside to preserve the directory structure.
$ cp -r passwd passwd-decrypted
$ find passwd-decrypted -type f -name '*.gpg' -deleteAnd decrypt.
$ find passwd -type f -name '*.gpg' -exec gpg --output 'passwd-decrypted/{}.txt' --decrypt '{}' \;You can remove the extension too with any bash-compatible shell.
$ shopt -s globstar # enables recursive glob for bash 4+
$ for f in **/*.gpg.txt; do mv "$f" "${f/%.gpg.txt/}"; doneNow we have a directory full of decrypted passwords.
Importing into Bitwarden
Bitwarden expects either csv or json with
a
specific format. The issue at this point is converting the free
form text format that pass allows, to a more structured
format that Bitwarden expects. This solely depends on how you have
structured your pass passwords. Mine are in the following
format:
<password>
username: <username>
email: <email>
www: <url>
totpauth://...
multiline free-form notes
Unfortunately, even though more recently I've tried to adhere to
this format, I haven't always. So there are a lot of files without
much structure, which means I have to manually import them. The only
reliable part of my password collection is the first line, and if
exists, otpauth://.
set -eux
function add {
filename="$1"
folder=$(dirname "${filename}")
if [[ "x$folder" = "x." ]]; then
name=$(basename "${filename}")
else
name="${folder}-"$(basename "${filename}")
fi
password=$(cat "$filename" | head -n 1)
username=$(cat "$filename" | grep -E '^(email|username):' | head -n 1 | cut -d: -f2- | sed 's/^[ \t]*//')
totp=$(cat "$filename" | grep otpauth)
url=$(cat "$filename" | grep -E '^(url|www|website):' | head -n 1 | cut -d: -f2- | sed 's/^[ \t]*//')
notes=$(cat "$filename")
echo -n "Adding $name..."
item_template=$(bw get template item)
login_template=$(bw get template item.login)
item_login=$(echo $login_template | jq --arg u "${username}" '.username=$u' | jq --arg p "${password}" '.password=$p' | jq ".totp=\"${totp}\"" | jq ".uris=[\"${url}\"]")
item=$(echo $item_template | jq ".name=\"${name}\"" | jq ".login=${item_login}" | jq --arg n "${notes}" '.notes=$n')
echo "$item" | bw encode | bw create item >/dev/null
echo "done"
}
# find * ... to remove the preceeding ./
find /path/to/passwd/decrypted/* -type f | while read f; do add "$f"; doneNote that the above script is extremely hacky and fails at the mere sight of anything being imperfect. Use with caution. It does handle quotes in passwords though, which is nice.
And finally sync.
$ bw syncAt last I can click to autofill everywhere I go!