Extracting 2FA codes from the abandoned 'Authenticator Plus' (ios)

3rd April 2024 – 677 words

Recently, I moved iPhones and wanted to open my 2FA keys with the App “Authenticator Plus” - But Apple has removed it from the App Store. Unfortunately, the developer has gone inactive and the app is abandoned, hopefully, they are all right :/

But, I still had the app on my old iPhone and wanted to extract the keys. Here is how I did it:

Retrieve database

The App-Store discussion above outlines most of what I repeat here. Also, this blog post helped a lot: Nigelsim.org: Extracting Authenticator Plus

The app is also released for Android, so it should be similar. Here is how I did it on iOS:

  1. Connect iPhone to Mac - Open Finder -> Select your iPhone on the left. Go to files -> Apps -> Authenticator Plus
  2. Drag & Drop the Folder “Backup” somewhere on your Mac

iTunes file dialog with Authenticator

Extract OTP URIs from encrypted database

The database is encrypted. You can either use sqlcipher (CLI) or DB Browser for SQLite (GUI) to open it.

brew install sqlcipher

# or

brew install --cask db-browser-for-sqlite

Open the database:

$ sqlcipher authplus.db

PRAGMA cipher_compatibility = 3;
PRAGMA kdf_iter = 64000;
PRAGMA cipher_page_size = 1024;
PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1;
PRAGMA cipher_hmac_algorithm = HMAC_SHA1;

SELECT 'otpauth://totp/' || REPLACE(REPLACE(email, '@', '%40'), ' ', '%20') || '?secret=' || secret || '&issuer=' || issuer FROM accounts;

If you get Parse error: file is not a database (26) your passphrase is wrong.

Copy the output from the SELECT statement for the next step:

SELECT 'otpauth://totp/' || REPLACE(REPLACE(email, '@', '%40'), ' ', '%20') || '?secret=' || secret || '&issuer=' || issuer FROM accounts;

Make QR-codes (Ruby)

This select statement above will give you the OTP-uris. To make it seamless, we now make QR codes from them. DO NOT USE AN ONLINE TOOL - those otp urls represent your 2FA keys, so you should not share them with anyone!

I tried the Python script from Nigelsim’s post, but I have no patience for venv / Homebrew Python shite, and gave up on the first error message in relation with Python.

Rather, I wrote a small ruby script. With bundler/inline it will automatically download the required Gem on load, without any env stuff. It will generate a HTML file with all the QR codes, that you also could print out or just open in the browser.

require 'bundler/inline'

qr_codes = [
# paste the otp output here

gemfile do
  source 'https://rubygems.org'
  gem 'rqrcode'
  gem 'pry'

imgs = []

qr_codes.each do |qr_code|
  qr = RQRCode::QRCode.new(qr_code)
  png = qr.as_png.to_data_url

  imgs << <<~HTML
    <div style='margin: 200px 0;'>
      <h3 style='font-family: ui-sans-serif'>#{qr_code}</h3>
      <img src="#{png}" style='width: 400px;'/>

File.write('qrcodes.html', imgs.join("\n"))
puts "Generated qrcodes.html"

Run it with ruby script.rb and open the generated qrcodes.html in your browser. You can now scan the QR codes with your new 2FA app.