mirror of
https://github.com/scito/extract_otp_secret_keys.git
synced 2025-12-11 09:06:38 +01:00
some renaming and README updating
This commit is contained in:
parent
8d8b993f12
commit
160a558825
3 changed files with 95 additions and 50 deletions
101
README.md
101
README.md
|
|
@ -1,8 +1,8 @@
|
|||
# Extract TOTP/HOTP secret keys from Google Authenticator
|
||||
|
||||
[](https://github.com/scito/extract_otp_secret_keys/actions/workflows/ci.yml)
|
||||
[](https://github.com/scito/extract_otp_secret_keys/actions/workflows/ci.yml)
|
||||

|
||||
[](https://github.com/scito/extract_otp_secret_keys/actions/workflows/ci_docker.yml)
|
||||
[](https://github.com/scito/extract_otp_secret_keys/actions/workflows/ci_docker.yml)
|
||||

|
||||
[](https://github.com/scito/extract_otp_secret_keys/blob/master/Pipfile.lock)
|
||||

|
||||
|
|
@ -16,7 +16,8 @@ TODO add src/
|
|||
TODO rename extract_otp_secret_keys
|
||||
|
||||
Extract two-factor authentication (2FA, TFA, OTP) secret keys from export QR codes of "Google Authenticator" app.
|
||||
The secret and otp values can be printed and exported to json or csv. The QR codes can be printed or saved as PNG images.
|
||||
The QR codes can captured from the camera in a GUI, imported from images or from text files containing the QR code data.
|
||||
The secret and otp values can be printed and exported to json or csv, as well as printed or saved as PNG images.
|
||||
|
||||
## Installation
|
||||
|
||||
|
|
@ -25,7 +26,7 @@ cd extract_otp_secret_keys
|
|||
|
||||
## Usage
|
||||
|
||||
### Capture QR codes from camera
|
||||
### Capture QR codes from camera (since v2.0.0)
|
||||
|
||||
1. Open "Google Authenticator" app on the mobile phone
|
||||
2. Export the QR codes from "Google Authenticator" app
|
||||
|
|
@ -36,7 +37,7 @@ cd extract_otp_secret_keys
|
|||
|
||||

|
||||
|
||||
### With builtin QR decoder from image files
|
||||
### With builtin QR decoder from image files (since v2.0.0)
|
||||
|
||||
1. Open "Google Authenticator" app on the mobile phone
|
||||
2. Export the QR codes from "Google Authenticator" app
|
||||
|
|
@ -59,7 +60,7 @@ cd extract_otp_secret_keys
|
|||
|
||||
## Program help: arguments and options
|
||||
|
||||
<pre>usage: extract_otp_secrets.py [-h] [--camera NUMBER] [--qr {QREADER,DEEP_QREADER,ZBAR,CV2,CV2_WECHAT}] [--json FILE] [--csv FILE] [--keepass FILE] [--printqr] [--saveqr DIR] [--no-color] [--verbose | --quiet] [infile ...]
|
||||
<pre>usage: extract_otp_secrets.py [-h] [--camera NUMBER] [--qr {ZBAR,QREADER,QREADER_DEEP,CV2,CV2_WECHAT}] [--json FILE] [--csv FILE] [--keepass FILE] [--printqr] [--saveqr DIR] [--no-color] [--verbose | --quiet] [infile ...]
|
||||
|
||||
Extracts one time password (OTP) secret keys from QR codes, e.g. from Google Authenticator app.
|
||||
If no infiles are provided, the QR codes are interactively captured from the camera.
|
||||
|
|
@ -71,7 +72,7 @@ positional arguments:
|
|||
options:
|
||||
-h, --help show this help message and exit
|
||||
--camera NUMBER, -C NUMBER camera number of system (default camera: 0)
|
||||
--qr {QREADER,DEEP_QREADER,ZBAR,CV2,CV2_WECHAT}, -Q {QREADER,DEEP_QREADER,ZBAR,CV2,CV2_WECHAT}
|
||||
--qr {ZBAR,QREADER,QREADER_DEEP,CV2,CV2_WECHAT}, -Q {ZBAR,QREADER,QREADER_DEEP,CV2,CV2_WECHAT}
|
||||
QR reader (default: ZBAR)
|
||||
--json FILE, -j FILE export json file or - for stdout
|
||||
--csv FILE, -c FILE export csv file or - for stdout
|
||||
|
|
@ -102,40 +103,11 @@ For protobuf versions 3.14.0 or similar or Python 3.6, use the extract_otp_secre
|
|||
|
||||
### Shared libs installation for reading QR code images
|
||||
|
||||
For reading QR code images the zbar library must be installed.
|
||||
If you do not extract directly from images, you do not need to install the zbar shared library.
|
||||
For reading QR code images the zbar library must be installed for `ZBAR` QR reader.
|
||||
If you do not extract directly from images or using catpuring from camera, you do not need to install the zbar shared library.
|
||||
|
||||
For a detailed installation documentation of [pyzbar](https://github.com/NaturalHistoryMuseum/pyzbar#installation).
|
||||
|
||||
#### Windows
|
||||
|
||||
The zbar DLLs are included with the Windows Python wheels. On other operating systems, you will need to install the zbar shared library.
|
||||
|
||||
TODO Write installation, not error message
|
||||
|
||||
##### Windows error message
|
||||
|
||||
If you see an ugly ImportError when importing [pyzbar](https://pypi.org/project/pyzbar/) on Windows you will most likely need the [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.
|
||||
|
||||
```
|
||||
Traceback (most recent call last):
|
||||
File "C:\Users\Admin\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\pyzbar\zbar_library.py", line 58, in load
|
||||
dependencies, libzbar = load_objects(Path(''))
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "C:\Users\Admin\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\pyzbar\zbar_library.py", line 50, in load_objects
|
||||
deps = [
|
||||
^
|
||||
File "C:\Users\Admin\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\pyzbar\zbar_library.py", line 51, in <listcomp>
|
||||
cdll.LoadLibrary(str(directory.joinpath(dep)))
|
||||
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.496.0_x64__qbz5n2kfra8p0\Lib\ctypes\__init__.py", line 454, in LoadLibrary
|
||||
return self._dlltype(name)
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.496.0_x64__qbz5n2kfra8p0\Lib\ctypes\__init__.py", line 376, in __init__
|
||||
self._handle = _dlopen(self._name, mode)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
FileNotFoundError: Could not find module 'libiconv.dll' (or one of its dependencies). Try using the full path with constructor syntax.
|
||||
```
|
||||
|
||||
#### Linux (Debian, Ubuntu, ...)
|
||||
|
||||
sudo apt-get install libzbar0
|
||||
|
|
@ -152,6 +124,10 @@ FileNotFoundError: Could not find module 'libiconv.dll' (or one of its dependenc
|
|||
|
||||
brew install zbar
|
||||
|
||||
#### Windows
|
||||
|
||||
The zbar DLLs are included with the Windows Python wheels. However, you might need 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.
|
||||
|
||||
## Examples
|
||||
|
||||
### Printing otp secrets form text file
|
||||
|
|
@ -193,7 +169,12 @@ FileNotFoundError: Could not find module 'libiconv.dll' (or one of its dependenc
|
|||
|
||||
* Free and open source
|
||||
* Supports Google Authenticator exports (and compatible apps like Aegis Authenticator)
|
||||
* Captures the the QR codes directly from the camera using QR code detection (based on OpenCV)
|
||||
* Captures the the QR codes directly from the camera using different QR code readers (based on OpenCV)
|
||||
* ZBAR: fast and reliable, good for images and video capture (default/recommended) [pyzbar](https://github.com/NaturalHistoryMuseum/pyzbar)
|
||||
* QREADER: fast [QReader](https://github.com/Eric-Canas/QReader)
|
||||
* QREADER_DEEP: slow, not good for camera [QReader](https://github.com/Eric-Canas/QReader)
|
||||
* CV2: fast [QRCodeDetector](https://docs.opencv.org/4.x/de/dc3/classcv_1_1QRCodeDetector.html)
|
||||
* CV2_WECHAT: fast [WeChatQRCode](https://docs.opencv.org/4.x/dd/d63/group__wechat__qrcode.html)
|
||||
* Supports TOTP and HOTP
|
||||
* Generates QR codes
|
||||
* Exports to various formats:
|
||||
|
|
@ -390,6 +371,8 @@ docker run --rm -v "$(pwd)":/files:ro extract_otp_secrets example_export.txt
|
|||
docker run --rm -v "$(pwd)":/files:ro extract_otp_secrets example_export.png
|
||||
```
|
||||
|
||||
TODO link to docker/github repos
|
||||
|
||||
docker run --rm -v "$(pwd)":/files:ro -i extract_otp_secrets = < example_export.png
|
||||
docker run --rm -v "$(pwd)":/files:ro -i --device="/dev/video0:/dev/video0" --env="DISPLAY" -v /tmp/.X11-unix:/tmp/.X11-unix:ro extract_otp_secrets
|
||||
docker run --pull always --rm -v "$(pwd)":/files:ro -i --device="/dev/video0:/dev/video0" --env="DISPLAY" -v /tmp/.X11-unix:/tmp/.X11-unix:ro scit0/extract_otp_secrets
|
||||
|
|
@ -410,6 +393,17 @@ docker pull scit0/extract_otp_secrets_only_txt
|
|||
docker pull ghcr.io/scito/extract_otp_secrets
|
||||
docker pull ghcr.io/scito/extract_otp_secrets_only_txt
|
||||
|
||||
### Docker examples
|
||||
|
||||
|
||||
docker run --pull always --rm -v \"$(pwd)\":/files:ro scit0/extract_otp_secrets example_export.png
|
||||
|
||||
docker run --pull always --rm -i -v \"$(pwd)\":/files:ro scit0/extract_otp_secrets_only_txt - < example_export.txt
|
||||
|
||||
cat example_export.txt | docker run --pull always --rm -i -v \"$(pwd)\":/files:ro scit0/extract_otp_secrets_only_txt - -c - > example_out.csv
|
||||
|
||||
docker run --pull always --rm -v "$(pwd)":/files:ro -i --device="/dev/video0:/dev/video0" --env="DISPLAY" -v /tmp/.X11-unix:/tmp/.X11-unix:ro scit0/extract_otp_secrets
|
||||
|
||||
## Tests
|
||||
|
||||
### PyTest
|
||||
|
|
@ -484,6 +478,35 @@ pip install -U -r requirements.txt
|
|||
|
||||
https://github.com/opencv/opencv/issues/23072
|
||||
|
||||
## Problems and Troubleshooting
|
||||
|
||||
### Windows error message
|
||||
|
||||
If you see an ugly ImportError on Windows you will most likely need the [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.
|
||||
|
||||
This library shared library is required by [pyzbar](https://pypi.org/project/pyzbar/).
|
||||
|
||||
```
|
||||
Traceback (most recent call last):
|
||||
File "C:\Users\Admin\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\pyzbar\zbar_library.py", line 58, in load
|
||||
dependencies, libzbar = load_objects(Path(''))
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "C:\Users\Admin\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\pyzbar\zbar_library.py", line 50, in load_objects
|
||||
deps = [
|
||||
^
|
||||
File "C:\Users\Admin\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\pyzbar\zbar_library.py", line 51, in <listcomp>
|
||||
cdll.LoadLibrary(str(directory.joinpath(dep)))
|
||||
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.496.0_x64__qbz5n2kfra8p0\Lib\ctypes\__init__.py", line 454, in LoadLibrary
|
||||
return self._dlltype(name)
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.496.0_x64__qbz5n2kfra8p0\Lib\ctypes\__init__.py", line 376, in __init__
|
||||
self._handle = _dlopen(self._name, mode)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
FileNotFoundError: Could not find module 'libiconv.dll' (or one of its dependencies). Try using the full path with constructor syntax.
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Related projects
|
||||
|
||||
* [ZBar](https://github.com/mchehab/zbar) is an open source software suite for reading bar codes from various sources, including webcams.
|
||||
|
|
|
|||
27
build.sh
27
build.sh
|
|
@ -82,6 +82,7 @@ interactive=true
|
|||
ignore_version_check=true
|
||||
clean=false
|
||||
build_docker=true
|
||||
run_gui=true
|
||||
|
||||
while test $# -gt 0; do
|
||||
case $1 in
|
||||
|
|
@ -94,6 +95,7 @@ while test $# -gt 0; do
|
|||
echo "-a Automatic mode"
|
||||
echo "-C Ignore version check"
|
||||
echo "-D No docker build"
|
||||
echo "-G No not run gui"
|
||||
echo "-c Clean"
|
||||
echo "-h, --help Help"
|
||||
quit
|
||||
|
|
@ -110,6 +112,10 @@ while test $# -gt 0; do
|
|||
build_docker=false
|
||||
shift
|
||||
;;
|
||||
-G)
|
||||
run_gui=false
|
||||
shift
|
||||
;;
|
||||
-c)
|
||||
clean=true
|
||||
shift
|
||||
|
|
@ -204,7 +210,7 @@ fi
|
|||
|
||||
# Upgrade pip requirements
|
||||
|
||||
cmd="sudo pip install --upgrade pip"
|
||||
cmd="sudo pip install -U pip"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
|
|
@ -266,7 +272,7 @@ eval "$cmd"
|
|||
|
||||
# pip install
|
||||
|
||||
cmd="$PIP install -e ."
|
||||
cmd="$PIP install -U -e ."
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
|
|
@ -324,6 +330,7 @@ if $build_docker; then
|
|||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
|
||||
# Build extract_otp_secrets (Debian)
|
||||
cmd="docker build . -t extract_otp_secrets --pull --build-arg RUN_TESTS=false"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
|
|
@ -333,7 +340,11 @@ if $build_docker; then
|
|||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="docker run --rm -i -v \"$(pwd)\":/files:ro extract_otp_secrets - < example_export.txt"
|
||||
cmd="cat mple_export.txt | docker run --rm -i -v \"$(pwd)\":/files:ro extract_otp_secrets - -c - > example_output.csv"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
cmd="docker run --rm -i -v \"$(pwd)\":/files:ro extract_otp_secrets = < example_export.png"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
|
|
@ -344,10 +355,20 @@ if $build_docker; then
|
|||
cmd="docker image prune -f || echo 'No docker image pruned'"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
|
||||
if $run_gui; then
|
||||
cmd="docker run --pull always --rm -v "$(pwd)":/files:ro --device=\"/dev/video0:/dev/video0\" --env=\"DISPLAY\" -v /tmp/.X11-unix:/tmp/.X11-unix:ro extract_otp_secrets &"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
fi
|
||||
eval "$cmd"
|
||||
fi
|
||||
|
||||
if $run_gui; then
|
||||
cmd="$PYTHON src/extract_otp_secrets.py &"
|
||||
if $interactive ; then askContinueYn "$cmd"; else echo -e "${cyan}$cmd${reset}";fi
|
||||
eval "$cmd"
|
||||
fi
|
||||
|
||||
echo -e "${greenBold}Sucessful${reset}"
|
||||
|
||||
quit
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# TODO rewrite
|
||||
# Extract two-factor authentication (2FA, TFA) secret keys from export QR codes of "Google Authenticator" app
|
||||
#
|
||||
# Usage:
|
||||
|
|
@ -118,7 +119,7 @@ Otps = List[Otp]
|
|||
# workaround for PYTHON <= 3.9: OtpUrls = list[OtpUrl]
|
||||
OtpUrls = List[OtpUrl]
|
||||
|
||||
QRMode = Enum('QRMode', ['QREADER', 'DEEP_QREADER', 'ZBAR', 'CV2', 'CV2_WECHAT'], start=0)
|
||||
QRMode = Enum('QRMode', ['ZBAR', 'QREADER', 'QREADER_DEEP', 'CV2', 'CV2_WECHAT'], start=0)
|
||||
|
||||
|
||||
# Constants
|
||||
|
|
@ -256,9 +257,9 @@ def extract_otps_from_camera(args: Args) -> Otps:
|
|||
log_error("Failed to capture image from camera")
|
||||
break
|
||||
try:
|
||||
if qr_mode in [QRMode.QREADER, QRMode.DEEP_QREADER]:
|
||||
if qr_mode in [QRMode.QREADER, QRMode.QREADER_DEEP]:
|
||||
found, bbox = qreader.detect(img)
|
||||
if qr_mode == QRMode.DEEP_QREADER:
|
||||
if qr_mode == QRMode.QREADER_DEEP:
|
||||
otp_url = qreader.detect_and_decode(img, True)
|
||||
elif qr_mode == QRMode.QREADER:
|
||||
otp_url = qreader.decode(img, bbox) if found else None
|
||||
|
|
@ -448,8 +449,8 @@ def convert_img_to_otp_url(filename: str, args: Args) -> OtpUrls:
|
|||
|
||||
qr_mode = QRMode[args.qr]
|
||||
otp_urls: OtpUrls = []
|
||||
if qr_mode in [QRMode.QREADER, QRMode.DEEP_QREADER]:
|
||||
otp_url = QReader().detect_and_decode(img, qr_mode == QRMode.DEEP_QREADER)
|
||||
if qr_mode in [QRMode.QREADER, QRMode.QREADER_DEEP]:
|
||||
otp_url = QReader().detect_and_decode(img, qr_mode == QRMode.QREADER_DEEP)
|
||||
otp_urls.append(otp_url)
|
||||
elif qr_mode == QRMode.CV2:
|
||||
otp_url, _, _ = cv2.QRCodeDetector().detectAndDecode(img)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue