Created
November 6, 2017 13:59
-
-
Save janbraiins/4ba1d7116791aca1d9e4962113d7ecae to your computer and use it in GitHub Desktop.
Conversion tool for google authenticator to FreeOTP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# | |
# Why: | |
# | |
# Currently, there is no easy way how to transfer all secrets from a google authenticator to a new device if: | |
# | |
# - the new device is not rooted (no way to push/access the sqlite DB of google authenticator) | |
# - you are not willing to enter every secret manually (assuming you have the sqlite DB from the old device) | |
# | |
# However, if you are willing to replace google authenticator for | |
# FreeOTP, you can populate the DB quite efficiently as long as you | |
# are able to get the Sqlite database of the Google Auth from the | |
# original device. | |
# | |
# Steps: | |
# - Fetch the google authenticator database from the old device (requires root) | |
# adb pull /data/data/com.google.android.apps.authenticator2/databases/databases | |
# | |
# - Create a backup of the freeotp to get the empty .xml: | |
# adb backup -noapk org.fedorahosted.freeotp | |
# | |
# - Unpack the backup via android: backup https://sourceforge.net/projects/adbextractor/files/latest/download | |
# java -jar abe.jar unpack backup.ab freeotp.tar | |
# tar xvf freeotp.tar | |
# | |
# - Run the script with the google auth database that has been retrieved from an old device: | |
# ./gauth2freeotp.py ./databases | |
# | |
# - Edit/Append the result into apps/org.fedorahosted.freeotp/sp/tokens.xml | |
# | |
# - Pack the result into the .tar | |
# find apps/ -type f | pax -wd > freeotpnew.tar | |
# | |
# - Create a valid Android backup from the tar | |
# java -jar abe.jar pack freeotpnew.tar otp.ab | |
# | |
# - Finally, restore the OTP database on a new device | |
# adb restore otp.ab | |
import base64 | |
import array | |
import sqlite3 | |
import sys | |
db = sqlite3.connect(sys.argv[1]) | |
cursor = db.cursor() | |
secret_tmpl = '<string name="{0}">{{"algo":"SHA1","counter":0,"digits":6,"issuerExt":"{0}","label":"vvv","period":30,"secret":[{1}],"type":"TOTP"}}</string>' | |
order_tmpl = '<string name="tokenOrder">[{0}]</string>' | |
cursor.execute('''SELECT email, secret, provider, issuer, original_name FROM accounts''') | |
ordered_names = [] | |
for (email, secret, provider, issuer, original_name) in cursor: | |
# base32 decoder requires the encoded string to be padded with '=' | |
# to multiple of 8 bytes | |
padding = ((len(secret) + 7) & 0xffffff8) - len(secret) | |
secret = secret + '=' * padding | |
# print('Padding = %s secret= %s' % (padding, secret)) | |
try: | |
secret_str = ','.join([str(x) for x in array.array('B', base64.b32decode(secret))]) | |
except Exception as e: | |
sys.stderr.write('Incorrect secret: %s, error: %s\n' % (secret, e)) | |
else: | |
print(' %s' % secret_tmpl.format(email, secret_str)) | |
ordered_names.append('"%s"' % email) | |
print(' %s' % order_tmpl.format(','.join(ordered_names))) | |
db.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment