GrapheneOS: Authenticator Plus to AndOTP

A lifetime ago I found myself switching from Android to iPhone. Part of migrating to my shiny new iPhone involved moving 10s of 2fa tokens trapped in Google Authenticator to a new application on the iPhone. Unfortunately, in 2015, GA had no export function and I couldn’t find a way to migrate the tokens. I began what seemed like an insurmountable task of re-enrolling all of my accounts in a new application, Authenticator Plus, which I ensured had an export function in the event I replaced my phone.

This week I found myself revisiting this daunting task with far greater success as I dump Apple and switch to GrapheneOS. The stakes are higher these days as I literally have hundreds of tokens, not the 10-20 I had in 2015. On the GrapheneOS side I chose to go with andOTP. It’s free, open source, and has and agreeable permission set. You can download andOTP from the F-Droid marketplace. The iPhone side was still using Authenticator Plus which exports to a SQLCipher DB you can pull from Finder.

I dug into what’s available for Authenticator Plus on the technical side finding this page. Specifically:


    A master password is required to use Authenticator Plus, which will never be sent outside your device
    Since master password is never stored outside only locally, there is no way to recover the data if master password is lost
    Data is stored in SQLCipher encrypted database

        SQLCipher uses 256-bit AES encryption
        Master password will be used to derive encryption key using 64000 PBKDF2 iterations(OpenSSL’s PKCS5_PBKDF2_HMAC_SHA1).
        SQLCipher uses OpenSSL libcrypto for all cryptographic functions

My attempts to decrypt the DB via sqlcipher PRAGMA keys failed, always returning file is not a database. This was frustrating, however, I could successfully open the DB in DB Browser for SQLite by specifying the master password and SQLCipher 3 defaults for the Encryption settings. This allowed me to save the sqlite database without encryption via Tools -> Set Encryption. If you leave the password blank encryption will be disabled.

Now that we have a decrypted sqlite DB, we need to migrate it’s data into a json file andOTP can import. Knowing I’m not the first person to trod these paths, I jump on github and search for "authenticator plus andOTP" which brings me to Adi’s repo. Skipping over the Docker sections, I dial in on authplus-to-andotp.py. It’s a standalone version however still expects the sqlcipher database, decryption didn’t work for me, and we now have an unencrypted sqlite db. Fork, edit, profit: authplus-to-andotp.py is a version that will parse our unencrypted database.

git clone https://github.com/VinceHillier/authplus-to-andotp-magiculator
cd authplus-to-andotp-magiculator
chmod +x authplus-to-andotp.py
./authplus-to-andotp.py -d ~/path/to/authplus.db
andOTP.json is now ready.

Now that we have our JSON file, copy it to your phone and import it. Open andOTP -> Three dots in the top right -> Backup -> Restore Backup.


Illustration of Vince

Vince Hillier is the President and Founder of Revenni Inc. He is an opensource advocate specializing in system engineering and infrastructure. Outside of building solid infrastructure that doesn't break the bank, he's interested in information security, privacy, and performance.