Google TOTP decode and self-generate
Pre-requirements
- An ubuntu system
- with python3 supports
- with python3-pip
- with package installer, likes apt
Step1. Export TOTP
Export your TOTP from Google Authenticator by using "Transfer Codes". Take a screenshot of the generated QR-Code.
Step 2. Decode the export
-
Install dependencies
sudo apt install -y libzbar0 protobuf-compiler pip install pyzbar pillow protobuf -
Write the protobuf created by Google
cat > migration.proto <<'EOF' syntax = "proto3"; message MigrationPayload { repeated OTPParameters otp_parameters = 1; } message OTPParameters { bytes secret = 1; string name = 2; string issuer = 3; Algorithm algorithm = 4; DigitCount digits = 5; OTPType type = 6; int64 counter = 7; } enum Algorithm { ALGORITHM_UNSPECIFIED = 0; SHA1 = 1; SHA256 = 2; SHA512 = 3; } enum DigitCount { DIGIT_COUNT_UNSPECIFIED = 0; SIX = 1; EIGHT = 2; } enum OTPType { OTP_TYPE_UNSPECIFIED = 0; HOTP = 1; TOTP = 2; } EOFprotoc --python_out=. migration.proto # File migration_pb2.py is generated -
Run the script
import base64 import migration_pb2 import pickle from pyzbar.pyzbar import decode from PIL import Image from urllib.parse import unquote img = Image.open('google_auth.jpg') decoded_objects = decode(img) if len(decoded_objects) == 0: print('No decoded object from given QRCode') exit() migrations = [datum for obj in decoded_objects if obj.type == 'QRCODE' and (datum := unquote(obj.data.decode('utf-8'))) and datum.startswith('otpauth-migration://')] if len(migrations) == 0: print('No valid migration extracted from given QRCode') exit() prots = [base64.b64decode(migration.replace('otpauth-migration://offline?data=', '', 1)) for migration in migrations] if len(prots) == 0: print('No correctly-formed migration extracted from given QRCode') exit() totps = [] payload = migration_pb2.MigrationPayload() payload.ParseFromString(prots[0]) for otp in payload.otp_parameters: totps.append({ "issuer": otp.issuer, "name": otp.name, "secret": otp.secret, }) with open('google_auth.bin', 'wb') as fout: pickle.dump(totps, fout) -
The script output, the decoded data, should be saved in file
google_auth.bin
Step 3. Generate the TOTP codes
- You only need
google_auth.binand following python script to re-generate TOTP codesimport hmac import hashlib import pickle import struct import time def gen_totp_code(secret, digits=6, period=30, algo=hashlib.sha1): counter = int(time.time() // period) msg = struct.pack(">Q", counter) h = hmac.new(secret, msg, algo).digest() offset = h[-1] & 0x0F code = struct.unpack(">I", h[offset:offset+4])[0] & 0x7fffffff return str(code % (10 ** digits)).zfill(digits) def load_totp_raws(): with open('google_auth.bin', 'rb') as fin: return pickle.load(fin) for otp in load_totp_raws(): print(otp['issuer']) print(otp['name']) print(gen_totp_code(otp['secret'])) print()
No comments to display
No comments to display