# Extract TOTP/HOTP secrets from QR codes exported by two-factor authentication apps [![CI tests](https://github.com/scito/extract_otp_secrets/actions/workflows/ci.yml/badge.svg)](https://github.com/scito/extract_otp_secrets/actions/workflows/ci.yml) ![coverage](https://img.shields.io/badge/coverage-94%25-brightgreen) [![CI docker](https://github.com/scito/extract_otp_secrets/actions/workflows/ci_docker.yml/badge.svg)](https://github.com/scito/extract_otp_secrets/actions/workflows/ci_docker.yml) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/protobuf) [![GitHub Pipenv locked Python version](https://img.shields.io/github/pipenv/locked/python-version/scito/extract_otp_secrets)](https://github.com/scito/extract_otp_secrets/blob/master/Pipfile.lock) ![protobuf version](https://img.shields.io/badge/protobuf-4.21.12-informational) [![License](https://img.shields.io/github/license/scito/extract_otp_secrets)](https://github.com/scito/extract_otp_secrets/blob/master/LICENSE) [![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/scito/extract_otp_secrets?sort=semver&label=version)](https://github.com/scito/extract_otp_secrets/tags) [![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://stand-with-ukraine.pp.ua) --- The Python script `extract_otp_secrets.py` extracts one time password (OTP) secrets from QR codes exported by two-factor authentication (2FA) apps such as "Google Authenticator". The exported QR codes from authentication apps can be read in three ways: 1. Capture from the system camera using a GUI, π 2. Read image files containing the QR codes, and π 3. Read text files containing the QR code data generated by third-party QR readers. The secret and otp values can be exported to json or csv files, as well as printed or saved to PNG images. β‘ **This project/script was renamed from `extract_otp_secret_keys` to `extract_otp_secrets`.** β‘ ## Usage ### Capture QR codes from camera (π since version 2.0) 1. Open "Google Authenticator" app on the mobile phone 2. Export the QR codes from "Google Authenticator" app (see [how to export](#how-to-export-otp-secrets-from-google-authenticator-app)) 3. Point the exported QR codes to the camera of your computer 4. Call this script without infile parameters: python src/extract_otp_secrets.py ![CV2 Capture from camera screenshot](cv2_capture_screenshot.png) Detected QR codes are surrounded with a frame. The color of the frame indicates the extracting result: * Green: The QR code is detected, decoded and the OTP secret was successfully extracted. * Red: The QR code is detected and decoded, but could not be successfully extracted. This is the case if a QR code not containing OTP data is captured. * Magenta: The QR code is detected, but could not be decoded. The QR code should be presented better to the camera or another QR reader could be used. ### With builtin QR decoder from image files (π since version 2.0) 1. Open "Google Authenticator" app on the mobile phone 2. Export the QR codes from "Google Authenticator" app (see [how to export](#how-to-export-otp-secrets-from-Google-Authenticator)) 4. Save the QR code as image file, e.g. example_export.png 5. Transfer the images files to the computer where his script is installed. 6. Call this script with the file as input: python src/extract_otp_secrets.py example_export.png ### With external QR decoder app from text files 1. Open "Google Authenticator" app on the mobile phone 2. Export the QR codes from "Google Authenticator" app (see [how to export](#how-to-export-otp-secrets-from-Google-Authenticator)) 3. Read QR codes with a third-party QR code reader (e.g. from another phone) 4. Save the captured QR codes from the QR code reader to a text file, e.g. example_export.txt. Save each QR code on a new line. (The captured QR codes look like `otpauth-migration://offline?data=...`) 5. Transfer the file to the computer where his script is installed. 6. Call this script with the file as input: python src/extract_otp_secrets.py example_export.txt ## Installation ``` git clone https://github.com/scito/extract_otp_secrets.git cd extract_otp_secrets pip install -U -r requirements.txt python src/extract_otp_secrets.py example_export.txt ``` In case this script is not starting properly, the debug mode can be activated by adding parameter `-d` in the command line. ### Installation of shared system libraries For reading QR codes with `ZBAR` QR reader, the zbar library must be installed. If you do not use the `ZBAR` QR reader, you do not need to install the zbar shared library. Note: The `ZBAR` QR reader is the showed for me the best results and is thus default QR Reader. For a detailed installation documentation of [pyzbar](https://github.com/NaturalHistoryMuseum/pyzbar#installation). #### Linux (Debian, Ubuntu, ...) sudo apt-get install libzbar0 #### Linux (OpenSUSE) sudo zypper install libzbar0 #### Linux (Fedora) sudo dnf install libzbar0 #### Mac OS X brew install zbar #### Windows ##### zbar The zbar DLLs are included with the Windows Python wheels. However, you might need additionally to install [Visual C++ Redistributable Packages for Visual Studio 2013](https://www.microsoft.com/en-US/download/details.aspx?id=40784). Install `vcredist_x64.exe` if using 64-bit Python, `vcredist_x86.exe` if using 32-bit Python. For more information see [pyzbar](https://github.com/NaturalHistoryMuseum/pyzbar) ##### OpenCV OpenCV requires [Visual C++ redistributable 2015](https://www.microsoft.com/en-us/download/details.aspx?id=48145). For more information see [opencv-python](https://pypi.org/project/opencv-python/) ## Program help: arguments and options
usage: extract_otp_secrets.py [-h] [--csv FILE] [--keepass FILE] [--json FILE] [--printqr] [--saveqr DIR] [--camera NUMBER] [--qr {ZBAR,QREADER,QREADER_DEEP,CV2,CV2_WECHAT}] [-i] [--no-color] [-d | -v | -q] [infile ...] Extracts one time password (OTP) secrets from QR codes exported by two-factor authentication (2FA) apps If no infiles are provided, a GUI window starts and QR codes are captured from the camera. positional arguments: infile a) file or - for stdin with 'otpauth-migration://...' URLs separated by newlines, lines starting with # are ignored; b) image file containing a QR code or = for stdin for an image containing a QR code options: -h, --help show this help message and exit --csv FILE, -c FILE export csv file or - for stdout --keepass FILE, -k FILE export totp/hotp csv file(s) for KeePass, - for stdout --json FILE, -j FILE export json file or - for stdout --printqr, -p print QR code(s) as text to the terminal (requires qrcode module) --saveqr DIR, -s DIR save QR code(s) as images to the given folder (requires qrcode module) --camera NUMBER, -C NUMBER camera number of system (default camera: 0) --qr {ZBAR,QREADER,QREADER_DEEP,CV2,CV2_WECHAT}, -Q {ZBAR,QREADER,QREADER_DEEP,CV2,CV2_WECHAT} QR reader (default: ZBAR) -i, --ignore ignore duplicate otps --no-color, -n do not use ANSI colors in console output -d, --debug enter debug mode, do checks and quit -v, --verbose verbose output -q, --quiet no stdout output, except output set by - examples: python extract_otp_secrets.py python extract_otp_secrets.py example_*.txt python extract_otp_secrets.py - < example_export.txt python extract_otp_secrets.py --csv - example_*.png | tail -n+2 python extract_otp_secrets.py = < example_export.png## Examples ### Printing otp secrets form text file python src/extract_otp_secrets.py example_export.txt ### Printing otp secrets from image file python src/extract_otp_secrets.py example_export.png ### Printing otp secrets multiple files python src/extract_otp_secrets.py example_*.txt python src/extract_otp_secrets.py example_*.png python src/extract_otp_secrets.py example_export.* python src/extract_otp_secrets.py example_*.txt example_*.png ### Printing otp secrets from stdin (text) python src/extract_otp_secrets.py - < example_export.txt ### Printing otp secrets from stdin (image) python src/extract_otp_secrets.py = < example_export.png ### Printing otp secrets csv to stdout python src/extract_otp_secrets.py --csv - example_export.txt ### Printing otp secrets csv to stdout without header line python src/extract_otp_secrets.py --csv - example_*.png | tail -n+2 ### Reading from stdin and printing to stdout cat example_*.txt | python src/extract_otp_secrets.py --csv - - | tail -n+2 ## Features * Free and open source * Supports Google Authenticator exports (and compatible apps like Aegis Authenticator) * Captures the the QR codes directly from the camera using different QR code libraries (based on OpenCV) (π since v2.0) * ZBAR: [pyzbar](https://github.com/NaturalHistoryMuseum/pyzbar) - fast and reliable, good for images and video capture (default and recommended) * QREADER: [QReader](https://github.com/Eric-Canas/QReader) * QREADER_DEEP: [QReader](https://github.com/Eric-Canas/QReader) - very slow in GUI * CV2: [QRCodeDetector](https://docs.opencv.org/4.x/de/dc3/classcv_1_1QRCodeDetector.html) * CV2_WECHAT: [WeChatQRCode](https://docs.opencv.org/4.x/dd/d63/group__wechat__qrcode.html) * Supports [TOTP](https://www.ietf.org/rfc/rfc6238.txt) and [HOTP](https://www.ietf.org/rfc/rfc4226.txt) standards * Generates QR codes * Exports to various formats: * CSV * JSON * Dedicated CSV for KeePass * QR code images * Supports reading from stdin and writing to stdout, thus pipes can be used * Handles multiple input files (π since v2.0) * Reads QR codes images: (See [OpenCV docu](https://docs.opencv.org/4.x/d4/da8/group__imgcodecs.html#ga288b8b3da0892bd651fce07b3bbd3a56)) (π since v2.0) * Portable Network Graphics - *.png * WebP - *.webp * JPEG files - *.jpeg, *.jpg, *.jpe * TIFF files - *.tiff, *.tif * Windows bitmaps - *.bmp, *.dib * JPEG 2000 files - *.jp2 * Portable image format - *.pbm, *.pgm, *.ppm *.pxm, *.pnm * Prints errors and warnings to stderr (π since v2.0) * Prints colored output (π since v2.0) * Many ways to run the script: * Native Python * pipenv * pip * venv * Docker * VSCode devcontainer * devbox * Prebuilt Docker images provided for amd64 and arm64 (π since v2.0) * Compatible with major platforms: * Linux * macOS * Windows * Uses UTF-8 on all platforms * Supports Python >= 3.7 * Provides a debug mode (-d) for analyzing import problems * Written in modern Python using type hints and following best practices * All these features are backed by tests ran nightly * All functionality in one Python script: src/extract_otp_secrets.py (except protobuf generated code in protobuf_generated_python) ## KeePass [KeePass 2.51](https://keepass.info/news/n220506_2.51.html) (released in May 2022) and newer [support the generation of OTPs (TOTP and HOTP)](https://keepass.info/help/base/placeholders.html#otp). KeePass can generate the second factor password (2FA) if the OTP secret is stored in `TimeOtp-Secret-Base32` string field for TOTP or `HmacOtp-Secret-Base32` string field for HOTP. You view or edit them in entry dialog on the 'Advanced' tab page. KeePass provides menu commands in the main window for generating one-time passwords ('Copy HMAC-Based OTP', 'Show HMAC-Based OTP', 'Copy Time-Based OTP', 'Show Time-Based OTP'). Furthermore, one-time passwords can be generated during auto-type using the {HMACOTP} and {TIMEOTP} placeholders. In order to simplify the usage of the second factor password generation in KeePass a specific KeePass CSV export is available with option `-keepass` or `-k`. This KeePass CSV file can be imported by the ["Generic CSV Importer" of KeePass](https://keepass.info/help/kb/imp_csv.html). If TOTP and HOTP entries have to be exported, then two files with an intermediate suffix .totp or .hotp will be added to the KeePass export filename. Example: - Only TOTP entries to export and parameter --keepass example_keepass_output.csv