byeCloud: Replace iCloud Keychain with KeePass

published on in category byeCloud , Tags: byecloud selfhosted keepass

iCloud Keychain has always been a love-hate relationship for me. I loved the simplicity of just being able to generate passwords right from the registration form of every page while it would also autofill passwords when I try to log in again. But I hated not being in charge of telling this thing to sync. Sometimes when I got a new device, the Keychain would just not start synching. Or passwords that I just created wouldn’t show up. Not to mention secure notes created in Keychain Access.app on the Mac that would not be visible on iOS.

I wanted to move my passwords to a secure, easy to use and technically simple alternative that provides me with all the capabilities I loved from iCloud Keychain but that gives back control into my hands to be able to decide when and what to synchronize. This article is part of the byeCloud series in which I try to replace iCloud with self-hosted services.

KeePass

I found KeePass just being the right thing for me. Well, sort of. I don’t use KeePass itself as a password manager. But alongside with it comes KDBX, an open source file format to securely store passwords in an encrypted container. And there happen to be dozens of clients that can read and write KDBX on almost every platform. What I ended up with was my keychain saved as a file and I could use every way you can imagine to synchronize it to all of my devices. Might it be WebDAV, a flash drive or a file share in your home network. It is simple and versatile.

I use my existing Nextcloud installation as described in byeCloud: File synching with Nextcloud to synchronize the file between my devices. On my Mac, the Nextcloud client synchronizes the file with my local disk every time it changes either upstream or locally. On iOS I use a KeePass client that has support for WebDAV, which is the backend used by Nextcloud to provide data.

MacPass & Integrations

On macOS, I found MacPass which is absolutely great. It is a native Cocoa app that provides the user experience you would imagine it from a first-class Mac app. No Java, no QT or GTK. It also supports global auto-typing, a feature that basically allows you to autofill every login form, even in native apps by executing a predefined sequence of keystrokes (defined per-password). There’s also a plugin called MacPassHTTP by the same developer that provides a HTTP-based API that can be consumed by clients like KeePassHTTP-Connector for Firefox or chromeIPass for Chrome/Chromium. This can be used to find passwords based on the URL of the page currently active and suggest and fill passwords from your KeePass DB. All of those tools are open source and work nicely together.

So I just created a new keychain file, secured it with a strong password and put it up to my Nextcloud.

Data migration

Migrating my data from iCloud Keychain to KeePass was probably the hardest thing to to here. I looked for different ways to achieve this but I found nothing that was easier than just copying the passwords manually. This is basically because of the API limitations of the Keychain framework in macOS. If you want to get your data out, you basically have to script the user interface to do the copy-pasting of your passwords to a CSV file. KeePass on the other side has no problem with this. Almost all clients provide import and export functionality to either CSV or XML files.

Finally I found a way to extract all the Safari passwords (iCloud Keychain) to a file that’s suitable for importing into KeePass but it’s a bit hacky. Here’s how to do it:

  1. Use an AppleScript to automate the UI of the Safari “Passwords” preference pane to copy/paste URLs, usernames and passwords to a text file in CSV format
  2. Save the text file as CSV and use a Ruby script from GitHub to convert it to the KeePass XML file format
  3. Import the generated XML file into MacPass

Extracting Safari passwords to a CSV file

I tested this procedure on macOS Mojave (10.14) with Safari 12 and it works flawlessly. Still I cannot guarantee that it will work in the future, as the UI might change and while Apple is anxious to not break APIs, they are willing to break UI behavior :-)

I found an AppleScript originally written for 1Password here: https://discussions.agilebits.com/discussion/comment/465689/#Comment_465689. You have to adjust two variables, first replace “PASSWORD” with your user password. No worries, this not used anywhere but to fill the password prompt in the Safari preferences - feel free to check it. Then there’s the number 207 in the script, which represents the total number of passwords that need to be extracted. I was too lazy to count and just used 1000 as a value and stopped the script right after the last password was reached - half assed but it works.

Open the Safari preferences and click the “Passwords” tab, without doing anything there. Don’t type your password. Then open Script Editor.app, paste the script, exchange the two variables and run the script. It will then enter the password and start copying all your passwords to a TextEdit.app document. This will take a while, so feel free to grab a coffee.

As described before, I killed the process after the last password in the table was written to TextEdit. Then convert the document to plain text (somewhere in the menu) and save it as, say safari-passwords.csv.

Converting the CSV file to a KeePass XML file

The next step is now to convert the CSV file to the KeePass XML file format. Luckily, lifepillar wrote a Ruby script to accomplish this and published it on GitHub. It’s called lifepillar/csv2keepassxml. Just clone the repository and do as described in the README.md file. If you use the Ruby version bundled with macOS, you have to run

sudo gem install htmlentities

to install the only dependency. The script needs to be called like this to convert the format provided by the AppleScript above:

./csv2keepassxml --title 1 --url 2 --username 3 --password 4 safari-passwords.csv

The script creates a file, in this case called safari-passwords.xml in the directory of your CSV file.

Importing the XML file into MacPass

The last step is easy, just create or open your KeePass DB in MacPass, select “Import” -> “Import XML…” from the menu and select your XML file.

Client side: iOS

On iOS for a long time I used MiniKeePass. When I found out that this can basically be considered dead as the last commit was from over one year ago, I had to find another solution. I came across KyPass 4 which is neither free nor open source. Instead it has one of the most horrible user interfaces I’ve ever seen on iOS. But it made me spending the 8 bucks because it supports automatic WebDAV synchronization and iOS 12 password autofill for some apps. This basically gives me “most of” the user experience I had with iCloud Keychain and I don’t have to worry about downloading and uploading my keychain changes every once in a while without overwriting changes I already made on another device. If you find another app that ticks both of those checkboxes, please let me know.