Mastodon

New Year, New Password Manager

The walled garden of the Apple ecosystem is certainly a cozy one, but good luck if you ever want to venture out beyond into other realms, such as Linux. For some use cases, iCloud is not only perfectly fine, but even preferable. I don’t foresee myself needing access to my Shortcuts on any non-iOS devices, so I can’t say I have any real qualms about cordoning them off onto their own platform. My documents, on the other hand? That’s another story. Likewise, what about photos and, probably most importantly, passwords? To put it succinctly, I want a solution that lets me have access to only what I need on each device/OS that I use, and nothing more. 2020 has brought some new themes for me; one of which is action. I’ve decided that the first step I’m going to take towards achieving world domination my goal is tackling the most important domain: passwords.

As aforementioned, things are pretty great within the confines of the walled garden; though by no means is it a panacea. The Keychain app has some pretty gaping holes with regard to its capabilities on each of the various platforms. On macOS, it’s pretty great! There’s a good concept of the different kinds of information that can be securely stored within it: login passwords, keys, notes, etc. Sadly, this notion does not translate over to iOS, and that’s a problem. Reinstalling macOS and the encryption key of your backup is stored in a secure note? You better write that down ahead of time or have another Mac around. May the gods have pity on you if you need to access any passwords on a device that isn’t logged into your iCloud account, or *gasp* isn’t running an Apple OS.

There are myriad third-party password managers. I prefer open source solutions where possible, so I first tried Bitwarden. It’s… okay. It does tick all the big boxes that Apple’s first-party solutions do, with the added benefits of having a web app (!) and being much more cross-platform. I understand why all of the clients are Electron/React-based, but I much prefer native apps. Being open source, and seeing some existing attempts at native clients, I thought I’d try to revive one. In doing so, I see why it stagnated: there’s little to no documentation, both outside of and within the source.

Enter: KeePass

KeePass is more of a protocol than a platform, and this is how it shines! There are native clients for just about every OS (at least that I use), and syncing it is as simple as passing a single file, the database, around through whatever means you please (in my case, Nextcloud). Clients can take care of merging or reverting changes as needed.

Hello darkness Applescript, my old friend…

Migrating between proprietary applications is never without hiccups, and Apple usually does a better job than most at enabling interoperablilty *cough* Microsoft *cough*. Keychain.app though, is the absolute antithesis of this. I understand that a password manager should probably have additional safeguards in place around data export, but crippling that functionality is not a safeguard. Login passwords, such as internet passwords, cannot be exported. The category of secure items that I most likely need available to me on other platforms is the hardest thing to extract. Having almost 250 login items in Keychain, I was not about to type my password in for each. Thankfully, there’s an App[lescript] for That™. I had to modify it to work on 10.14.6+, and if you’re reading this more than six months from date of publication, I’m sorry that you’ll probably have to modify it further to work for yourself, but here, in all of its horrendous glory, is a script to copy a given number of items from Keychain.app to a csv file.

set x to 1
tell application "Keychain Access"
activate
repeat while (x ≤ NUMBER_OF_ITEMS_TO_EXPORT)
tell application "System Events"
click text field 1 of row 1 of outline 1 of scroll area 1 of splitter group 1 of window "Keychain Access" of application process "Keychain Access"
keystroke return
delay 0.2
keystroke tab
delay 0.2
keystroke tab
delay 0.2
keystroke tab
delay 0.2
keystroke "c" using command down
delay 0.2
do shell script "/usr/bin/pbpaste | xargs -I {} echo -n {}\",\" >> ~/exports.csv"
delay 0.2
keystroke tab using shift down
delay 0.2
keystroke "c" using command down
delay 0.2
do shell script "/usr/bin/pbpaste | xargs -I {} echo -n {}\",\" >> ~/exports.csv"
delay 0.2
click checkbox "Show password:" of tab group 1 of window 1 of application process "Keychain Access"
delay 0.2
keystroke KEYCHAIN_PASSWORD
delay 0.2
keystroke return
delay 0.2
keystroke tab using shift down
delay 0.2
keystroke tab using shift down
delay 0.2
keystroke tab using shift down
delay 0.2
keystroke "c" using command down
delay 0.2
do shell script "/usr/bin/pbpaste | xargs -I {} echo {}\",\" >> ~/exports.csv"
delay 0.2
click UI element 2 of window 1 of application process "Keychain Access"
delay 0.2
key code 125
delay 0.2
end tell
set x to (x + 1)
end repeat
end tell

You’ll want to substitute the number of items, as well as your password, and beware that it obviously exports them as plaintext (in plain text), so don’t save it to your Documents or Desktop folders if those are synced via iCloud. Additionally, you can sort items by “Kind” if you’re only interested in exporting certain types, such as login items. Then sit back, relax, maybe prepare a beverage, because it might take a while (About a half of an hour, in my case).

Part the Second, Converting to KeePass

KeePass has a diverse ecosystem of scripts and utilities for importing a variety of data formats through a client. For our purposes, there’s csv2keepassxml, an incredibly flexible Ruby utility that converts data from, you guessed it, csv into an importable xml file. If, unlike me, you’re a Ruby expert or don’t care about littering your system with packages you’ll install once and probably never use again, feel free to skip the next two sections.

rbenv

Because I wasn’t developing web apps in 2008, I’m not a big fan of Ruby, but I am a fan of using virtual environments, especially for languages with system installations, such as Python and, you guessed it, Ruby, on macOS (for now). If you don’t care about such things, feel free to skip this section. For everyone else, there’s rbenv. Much like its Python counterpart, pyenv, installation is simple and can be accomplished via brew.

$
brew install rbenv

Follow the instructions given by the init command to set up your shell.

$
rbenv init

Finally, source your config or restart your terminal to make the changes take effect.

Usage is equally simple. To install a far more up-to-date version of Ruby than what macOS may (or in the future may not) even have, simply use the install command.

$
rbenv install

rbenv-gemset

Virtual environments aren’t terribly useful without dependency management. For rbenv, this is where rbenv-gemset comes in. A plugin for rbenv, it allows dependencies to be managed per-project and even reside within the project directory.

Installation is as easy as rbenv, as it’s also available via brew.

$
brew install rbenv-gemset

In the root of the project, create a gemset using the current version of Ruby.

$
rbenv gemset init

You can now use gem as you would normally, with the gems being installed to a directory in the root of your project.

csv2keepassxml

If you’re joining us from the beginning of this part, welcome back! csv2keepassxml is available not via brew, so let’s clone the repository from Github.

$
git clone https://github.com/lifepillar/csv2keepassxml

Create a gemset, and install csv2keepassxml's dependencies into it.

$
gem install htmlentities

If you used the format of the aforementioned applescript, the following will create a KeePass2 database file from the exported csv file.

$
./csv2keepassxml -t 1 -U 1 -u 2 -p 3 ~/keychain-export.csv

Note: Indices are 1-based. Unfortunately.

Clients, Clients Everywhere!

There are a plethora of KeePass clients out there. Here are the ones that I use, and for the most part recommend. For an added bonus, they’re all open source!

Conclusion

This is the first step in my journey towards building a private infrastructure for my personal data. Over the upcoming months, I’ll be looking into solutions for file storage and syncing, and then eventually services such as email, contacts, and calendars.