Recover FreeOTP Codes

1. Get an ADB shell and create the backup

adb shell

Then back up only the FreeOTP app:

adb backup -f freeotp-backup.ab -apk org.fedorahosted.freeotp

The output file is saved in the current directory.

2. Unpack the backup with Android Backup Extractor

https://github.com/nelenkov/android-backup-extractor

abe.jar unpack freeotp-backup.ab freeotp-backup.tar

Unpack the .tar file. The only file you need is tokens.xml inside the app's data directory.

3. Extract TOTP secrets with Python

Place tokens.xml in the same folder as the script (path: org.fedorahosted.freeotp/sp/tokens.xml):

#!/usr/bin/env python

import base64, json
import xml.etree.ElementTree as ET

verbose = False

root = ET.parse('org.fedorahosted.freeotp/sp/tokens.xml').getroot()
for secrets in root.findall('string'):
    name = secrets.get('name')
    if name == 'tokenOrder':
        continue

    secret_json = secrets.text
    print("secret name: {}".format(name))
    if verbose: print("secret json: {}".format(secret_json))
    token = json.loads(secret_json)
    token_secret = token["secret"]
    if verbose: print("token secret: {}".format(token_secret))
    secret = bytes((x + 256) & 255 for x in token_secret)
    if verbose: print("token secret bytes {}".format(secret))
    code = base64.b32encode(secret)
    print("token secret base64: {}".format(code.decode()))

The output is a Base32-encoded secret you can import into any TOTP app.