mirror of
https://github.com/token2/Migration-Toolset.git
synced 2026-06-22 14:42:21 -07:00
@@ -10,44 +10,19 @@ More information is available here https://www.token2.swiss/site/page/how-to-tra
|
||||
|
||||
## Packages used
|
||||
### Python
|
||||
The protobuf package of Google for proto3 is required for running this script. protobuf >= 3.14 is recommended.
|
||||
The protobuf package of Google for proto3 is required for running this script. protobuf >= 3.14 < 3.21 is recommended.
|
||||
|
||||
pip install protobuf
|
||||
pip install "protobuf<3.21"
|
||||
|
||||
### Other packages
|
||||
#### Note: the toolset uses the following third-party executables:
|
||||
**Windows**
|
||||
|
||||
*qrdecode.exe* - used to decode the contents of the QR code to text. This is a part of Zbar Code Reader project (http://zbar.sourceforge.net/)
|
||||
|
||||
*SimpleCodeGenerator.exe* - used to create a QR code from text. Created by Nir Sofer (https://www.nirsoft.net/utils/qr_code_generator.html)
|
||||
|
||||
Both can be downloaded from this repository or from the original websites.
|
||||
|
||||
**Linux**
|
||||
|
||||
*zbarimg* - used to decode the contents of the QR code to text. This is a part of Zbar Code Reader project (http://zbar.sourceforge.net/). Installation using the following command:
|
||||
|
||||
sudo apt-get install zbar-tools
|
||||
|
||||
*qrencode* - a tool used to create a QR code from text by Kentaro Fukuchi ( http://fukuchi.org/works/qrencode/ ). Installation using the following command:
|
||||
|
||||
sudo apt-get install qrencode
|
||||
|
||||
|
||||
|
||||
**Windows and Linux**
|
||||
|
||||
*qrscan.exe* - used to decode the contents of the QR code to text and to convert QR to svg. This is a part qrscan project (https://github.com/sayanarijit/qrscan)
|
||||
|
||||
## Usage syntax
|
||||
|
||||
### Windows
|
||||
|
||||
extract_otp_secret_keys-win.py --fromimg *png file* --moltofile *txt file* --htmlfile *html file*
|
||||
|
||||
### Linux
|
||||
|
||||
extract_otp_secret_keys-linux.py --fromimg *png file* --moltofile *txt file* --htmlfile *html file*
|
||||
|
||||
extract_otp_secret_keys.py --fromimg *png file* --moltofile *txt file* --htmlfile *html file*
|
||||
|
||||
### Command line parameters
|
||||
|
||||
@@ -61,10 +36,13 @@ extract_otp_secret_keys-linux.py --fromimg *png file* --moltofile *txt file* -
|
||||
|
||||
Windows - decode GA-QR.png contents to format for Molto2 bulk import
|
||||
|
||||
python3 extract_otp_secret_keys-win.py --fromimg C:\Temp\GA-QR.png --moltofile C:\Temp\Molto2-import-totp.txt
|
||||
python3 extract_otp_secret_keys.py --fromimg C:\Temp\GA-QR.png --moltofile C:\Temp\Molto2-import-totp.txt
|
||||
|
||||
Linux - decode GA-QR.png contents to html (list of QR codes ready for migration)
|
||||
|
||||
python3 extract_otp_secret_keys-win.py --fromimg /tmp/GA-QR.png --htmlfile /tmp/totp.html
|
||||
python3 extract_otp_secret_keys.py --fromimg /tmp/GA-QR.png --htmlfile /tmp/totp.html
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
- If Molto-2 USB Config Tool doesn't like the image use the moltofile output. Format is "Slot Seed Algorithm OTPLength TimeStep yes yes Title". Just copy it by hand over.
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1,175 +0,0 @@
|
||||
|
||||
|
||||
|
||||
SimpleCodeGenerator v1.00
|
||||
Copyright (c) 2021 Nir Sofer
|
||||
Web site: https://www.nirsoft.net/utils/qr_code_generator.html
|
||||
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
SimpleCodeGenerator is a simple tool for Windows that allows you to
|
||||
quickly generate QR Code for scanning with App on your Smartphone. You
|
||||
can display the QR Code on the screen, copy it to the clipboard and then
|
||||
paste it to another program (as image), or save it image file - .png ,
|
||||
.gif , .jpg , .tiff, or .bmp
|
||||
|
||||
SimpleCodeGenerator also allows you to generate QR Code from command line
|
||||
and save it as image file ( .png , .gif , .jpg , .tiff, or .bmp) without
|
||||
displaying any user interface.
|
||||
|
||||
|
||||
|
||||
System Requirements
|
||||
===================
|
||||
|
||||
|
||||
* This tool works on any version of Windows, starting from Windows XP
|
||||
and up to Windows 10. Both 32-bit and 64-bit systems are supported.
|
||||
* This tool is just a small standalone .exe file (Less than 100KB !)
|
||||
that you can run on any system without installing anything.
|
||||
|
||||
|
||||
|
||||
What you can do with QR Codes
|
||||
=============================
|
||||
|
||||
With this tool, you can create QR Codes that open a URL on the Web
|
||||
browser of your Smartphone, add a new contact to your Smartphone, add new
|
||||
Wi-Fi network to your Smartphone, open map in the specified
|
||||
latitude/longitude, and more.
|
||||
You simply have to type the correct QR Code string in
|
||||
SimpleCodeGenerator, generate the QR Code, and then scan it with QR Code
|
||||
reader App on your Smartphone.
|
||||
|
||||
You can read this article to learn how to compose the QR Code string that
|
||||
will do what you need.
|
||||
|
||||
|
||||
|
||||
Start Using SimpleCodeGenerator
|
||||
===============================
|
||||
|
||||
SimpleCodeGenerator doesn't require any installation process or
|
||||
additional DLL files. In order to start using it, simply run the
|
||||
executable file - SimpleCodeGenerator.exe
|
||||
After running SimpleCodeGenerator, you can type the URL or other QR
|
||||
string in the text-box just below the toolbar, and then press the
|
||||
'Generate QR Code' button or press the F5 key. The QR Code will be
|
||||
displayed instantly in the main window of SimpleCodeGenerator.
|
||||
Optionally, you can press F2 to copy the QR Code to the clipboard, and
|
||||
then paste it into another application, like MS-Word. You can also export
|
||||
the generated QR Code to png / gif / jpg / tiff / bmp file, by using the
|
||||
'Save QR Code To Image File' option (Ctrl+S).
|
||||
|
||||
|
||||
|
||||
Multiple Lines Mode
|
||||
===================
|
||||
|
||||
If your QR Code string contains multiple lines (like a vCard QR Code), Go
|
||||
to the Options menu, select the 'Multiple Lines Mode' option (or simply
|
||||
press F7), and then SimpleCodeGenerator will allow you to type a string
|
||||
with multiple lines.
|
||||
|
||||
|
||||
|
||||
Command-Line Options
|
||||
====================
|
||||
|
||||
|
||||
|
||||
/Show <QR Code String>
|
||||
This command generates the QR Code for the specified string, and displays
|
||||
it on the main window of SimpleCodeGenerator.
|
||||
|
||||
If your QR Code string contains multiple lines, you should use the '\r\n'
|
||||
escape sequence to specify the CR-LF characters. If your QR Code string
|
||||
contains the '\' character, you should specify this character twice
|
||||
('\\').
|
||||
|
||||
Examples:
|
||||
SimpleCodeGenerator.exe /Show
|
||||
"https://www.nirsoft.net/utils/qr_code_generator.html"
|
||||
SimpleCodeGenerator.exe /Show
|
||||
"BEGIN:VCARD\r\nVERSION:3.0\r\nN:Sofer;Nir;;;\r\nFN:Nir
|
||||
Sofer\r\nTITLE:Programmer\r\nEMAIL;TYPE=INTERNET;TYPE=WORK;TYPE=PREF:suppor
|
||||
t@nirsoft.net\r\nURL;TYPE=Homepage:https://www.nirsoft.net\r\nEND:VCARD"
|
||||
|
||||
/Save <QR Code String> <Image Filename> {Image Scaling}
|
||||
This command generates the QR Code for the specified string, and then
|
||||
exports it to the specified image filename (.png , .gif , .jpg , .tiff,
|
||||
or .bmp file).
|
||||
{Image Scaling} is an optional parameter that specifies the number of
|
||||
pixels to create in the image file for every pixel in the QR Code. For
|
||||
example: if you specify "10" - for every pixel in the QR Code, you will
|
||||
get 10x10 pixels in the image file. If you don't specify the {Image
|
||||
Scaling} value, the default scaling is 5.
|
||||
|
||||
If your QR Code string contains multiple lines, you should use the '\r\n'
|
||||
escape sequence to specify the CR-LF characters. If your QR Code string
|
||||
contains the '\' character, you should specify this character twice
|
||||
('\\').
|
||||
|
||||
|
||||
Examples:
|
||||
SimpleCodeGenerator.exe /Save
|
||||
"https://www.nirsoft.net/utils/qr_code_generator.html"
|
||||
"c:\temp\qrcode1.png" 10
|
||||
SimpleCodeGenerator.exe /Save "WIFI:T:WPA;S:MyWifi;P:WifiPass1234;;"
|
||||
"c:\temp\qrcode2.gif"
|
||||
|
||||
|
||||
|
||||
Translating SimpleCodeGenerator to other languages
|
||||
==================================================
|
||||
|
||||
In order to translate SimpleCodeGenerator to other language, follow the
|
||||
instructions below:
|
||||
1. Run SimpleCodeGenerator with /savelangfile parameter:
|
||||
SimpleCodeGenerator.exe /savelangfile
|
||||
A file named SimpleCodeGenerator_lng.ini will be created in the folder
|
||||
of SimpleCodeGenerator utility.
|
||||
2. Open the created language file in Notepad or in any other text
|
||||
editor.
|
||||
3. Translate all string entries to the desired language. Optionally,
|
||||
you can also add your name and/or a link to your Web site.
|
||||
(TranslatorName and TranslatorURL values) If you add this information,
|
||||
it'll be used in the 'About' window.
|
||||
4. After you finish the translation, Run SimpleCodeGenerator, and all
|
||||
translated strings will be loaded from the language file.
|
||||
If you want to run SimpleCodeGenerator without the translation, simply
|
||||
rename the language file, or move it to another folder.
|
||||
|
||||
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
This utility is released as freeware. You are allowed to freely
|
||||
distribute this utility via CD-ROM, DVD, Internet, or in any other way,
|
||||
as long as you don't charge anything for this and you don't sell it or
|
||||
distribute it as a part of commercial product. If you distribute this
|
||||
utility, you must include all files in the distribution package, without
|
||||
any modification !
|
||||
|
||||
|
||||
|
||||
Disclaimer
|
||||
==========
|
||||
|
||||
The software is provided "AS IS" without any warranty, either expressed
|
||||
or implied, including, but not limited to, the implied warranties of
|
||||
merchantability and fitness for a particular purpose. The author will not
|
||||
be liable for any special, incidental, consequential or indirect damages
|
||||
due to loss of data or any other reason.
|
||||
|
||||
|
||||
|
||||
Feedback
|
||||
========
|
||||
|
||||
If you have any problem, suggestion, comment, or you found a bug in my
|
||||
utility, you can send a message to support@nirsoft.net
|
||||
@@ -1,115 +0,0 @@
|
||||
# Based on the original script from : Scito (https://scito.ch)
|
||||
# Changes in this script:
|
||||
# 1. Changed the QR code generation method to SimpleCodeGenerator from Nir Sofer
|
||||
# 2. Changed export format to have HTML and Molto-2 compatible import file
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import fileinput
|
||||
import sys
|
||||
from urllib.parse import parse_qs, urlencode, urlparse, quote
|
||||
from os import path, mkdir, system, remove
|
||||
from re import sub, compile as rcompile
|
||||
import generated_python.google_auth_pb2
|
||||
arg_parser = argparse.ArgumentParser()
|
||||
arg_parser.add_argument('--verbose', '-v', help='verbose output', action='store_true')
|
||||
arg_parser.add_argument('--saveqr', '-s', help='save QR code(s) as images to the "qr" subfolder', action='store_true')
|
||||
arg_parser.add_argument('--printqr', '-p', help='print QR code(s) as text to the terminal', action='store_true')
|
||||
arg_parser.add_argument('--infile', help='file or - for stdin (default: -) with "otpauth-migration://..." URLs separated by newlines, lines starting with # are ignored')
|
||||
arg_parser.add_argument('--moltofile', help='save exctracted data in file compatible with Molto-2 format. If file does not exist a new file will be created.')
|
||||
arg_parser.add_argument('--htmlfile', help='save exctracted data in html file with QR codes for enrolling TOTP profiles to other apps or single profile tokens')
|
||||
arg_parser.add_argument('--fromimg', help='read otpauth-migration strings from a screenshot')
|
||||
args = arg_parser.parse_args()
|
||||
|
||||
verbose = args.verbose
|
||||
|
||||
# https://stackoverflow.com/questions/40226049/find-enums-listed-in-python-descriptor-for-protobuf
|
||||
def get_enum_name_by_number(parent, field_name):
|
||||
field_value = getattr(parent, field_name)
|
||||
return parent.DESCRIPTOR.fields_by_name[field_name].enum_type.values_by_number.get(field_value).name
|
||||
|
||||
def convert_secret_from_bytes_to_base32_str(bytes):
|
||||
return str(base64.b32encode(otp.secret), 'utf-8').replace('=', '')
|
||||
|
||||
#decode from image to text file
|
||||
if args.fromimg:
|
||||
system("zbarimg --raw "+args.fromimg+" > input_qr.txt ")
|
||||
args.infile = "input_qr.txt"
|
||||
|
||||
i = j = 0
|
||||
print('Starting the process')
|
||||
for line in (line.strip() for line in fileinput.input(args.infile)):
|
||||
if verbose: print(line)
|
||||
if line.startswith('#') or line == '': continue
|
||||
if not line.startswith('otpauth-migration://'): print('\nWARN: line is not a otpauth-migration:// URL\ninput file: {}\nline "{}"\nProbably a wrong file was given'.format(args.infile, line))
|
||||
parsed_url = urlparse(line)
|
||||
params = parse_qs(parsed_url.query)
|
||||
if not 'data' in params:
|
||||
print('\nERROR: no data query parameter in input URL\ninput file: {}\nline "{}"\nProbably a wrong file was given'.format(args.infile, line))
|
||||
sys.exit(1)
|
||||
data_encoded = params['data'][0]
|
||||
data = base64.b64decode(data_encoded)
|
||||
payload = generated_python.google_auth_pb2.MigrationPayload()
|
||||
payload.ParseFromString(data)
|
||||
i += 1
|
||||
if verbose: print('\n{}. Payload Line'.format(i), payload, sep='\n')
|
||||
line_count = -1
|
||||
#Count lines in Molto2-export.txt
|
||||
if args.moltofile:
|
||||
if path.exists(args.moltofile):
|
||||
|
||||
file = open(args.moltofile, "r")
|
||||
|
||||
for line in file:
|
||||
if line != "\n":
|
||||
line_count += 1
|
||||
file.close()
|
||||
|
||||
# pylint: disable=no-member
|
||||
for otp in payload.otp_parameters:
|
||||
j += 1
|
||||
|
||||
if verbose: print('\n{}. Secret Key'.format(j))
|
||||
else: print()
|
||||
print('Name: {}'.format(otp.name))
|
||||
secret = convert_secret_from_bytes_to_base32_str(otp.secret)
|
||||
#print('Secret: {}'.format(secret))
|
||||
if otp.issuer: print('Issuer: {}'.format(otp.issuer))
|
||||
print('Type: {}'.format(get_enum_name_by_number(otp, 'type')))
|
||||
url_params = { 'secret': secret }
|
||||
if otp.type == 1: url_params['counter'] = otp.counter
|
||||
if otp.issuer: url_params['issuer'] = otp.issuer
|
||||
otp_url = 'otpauth://{}/{}?'.format('totp' if otp.type == 2 else 'hotp', quote(otp.name)) + urlencode(url_params)
|
||||
if args.moltofile:
|
||||
with open(args.moltofile, 'a') as f:
|
||||
#Create text file with seed info
|
||||
f.write(str(line_count+j)+' '+secret+' sha1 6 30 yes yes '+otp.issuer+'\n')
|
||||
if args.htmlfile:
|
||||
with open(args.htmlfile, 'a') as f2:
|
||||
#Create html file with seed info in QR format
|
||||
keyURI="otpauth://totp/"+otp.name+"?secret="+secret#+"?issuer="+otp.issuer
|
||||
#Generate QR code image
|
||||
system ("qrencode '"+ keyURI + "' -o img/"+str(line_count+j)+".png")
|
||||
encoded = base64.b64encode(open("img/"+str(line_count+j)+".png", "rb").read())
|
||||
encoded2=encoded.decode('utf-8')
|
||||
remove("img/"+str(line_count+j)+".png")
|
||||
f2.write('TOTP Profile '+str(line_count+j)+':'+otp.name+"<br><img width=250 src='data:image/png;base64,"+encoded2+"'><pre>"+secret+"</pre><hr><br><br>")
|
||||
#empty input_qr.txt
|
||||
f = open('input_qr.txt', 'r+')
|
||||
f.truncate(0) # need '0' when using r+
|
||||
print(' ')
|
||||
print('Files have been generated:')
|
||||
print (args.htmlfile)
|
||||
print (args.moltofile)
|
||||
@@ -1,116 +0,0 @@
|
||||
# Based on the original script from : Scito (https://scito.ch)
|
||||
# Changes in this script:
|
||||
# 1. Changed the QR code generation method to SimpleCodeGenerator from Nir Sofer
|
||||
# 2. Changed export format to have HTML and Molto-2 compatible import file
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import fileinput
|
||||
import sys
|
||||
from urllib.parse import parse_qs, urlencode, urlparse, quote
|
||||
from os import path, mkdir, system, remove
|
||||
from re import sub, compile as rcompile
|
||||
import generated_python.google_auth_pb2
|
||||
arg_parser = argparse.ArgumentParser()
|
||||
arg_parser.add_argument('--verbose', '-v', help='verbose output', action='store_true')
|
||||
arg_parser.add_argument('--saveqr', '-s', help='save QR code(s) as images to the "qr" subfolder', action='store_true')
|
||||
arg_parser.add_argument('--printqr', '-p', help='print QR code(s) as text to the terminal', action='store_true')
|
||||
arg_parser.add_argument('--infile', help='file or - for stdin (default: -) with "otpauth-migration://..." URLs separated by newlines, lines starting with # are ignored')
|
||||
arg_parser.add_argument('--moltofile', help='save exctracted data in file compatible with Molto-2 format. If file does not exist a new file will be created.')
|
||||
arg_parser.add_argument('--htmlfile', help='save exctracted data in html file with QR codes for enrolling TOTP profiles to other apps or single profile tokens')
|
||||
arg_parser.add_argument('--fromimg', help='read otpauth-migration strings from a screenshot')
|
||||
args = arg_parser.parse_args()
|
||||
|
||||
verbose = args.verbose
|
||||
|
||||
# https://stackoverflow.com/questions/40226049/find-enums-listed-in-python-descriptor-for-protobuf
|
||||
def get_enum_name_by_number(parent, field_name):
|
||||
field_value = getattr(parent, field_name)
|
||||
return parent.DESCRIPTOR.fields_by_name[field_name].enum_type.values_by_number.get(field_value).name
|
||||
|
||||
def convert_secret_from_bytes_to_base32_str(bytes):
|
||||
return str(base64.b32encode(otp.secret), 'utf-8').replace('=', '')
|
||||
|
||||
#decode from image to text file
|
||||
if args.fromimg:
|
||||
system("qrdecode.exe --raw "+args.fromimg+" > input_qr.txt ")
|
||||
args.infile = "input_qr.txt"
|
||||
|
||||
i = j = 0
|
||||
print('Starting the process')
|
||||
for line in (line.strip() for line in fileinput.input(args.infile)):
|
||||
if verbose: print(line)
|
||||
if line.startswith('#') or line == '': continue
|
||||
if not line.startswith('otpauth-migration://'): print('\nWARN: line is not a otpauth-migration:// URL\ninput file: {}\nline "{}"\nProbably a wrong file was given'.format(args.infile, line))
|
||||
parsed_url = urlparse(line)
|
||||
params = parse_qs(parsed_url.query)
|
||||
if not 'data' in params:
|
||||
print('\nERROR: no data query parameter in input URL\ninput file: {}\nline "{}"\nProbably a wrong file was given'.format(args.infile, line))
|
||||
sys.exit(1)
|
||||
data_encoded = params['data'][0]
|
||||
data = base64.b64decode(data_encoded)
|
||||
payload = generated_python.google_auth_pb2.MigrationPayload()
|
||||
payload.ParseFromString(data)
|
||||
i += 1
|
||||
if verbose: print('\n{}. Payload Line'.format(i), payload, sep='\n')
|
||||
line_count = -1
|
||||
#Count lines in Molto2-export.txt
|
||||
if args.moltofile:
|
||||
if path.exists(args.moltofile):
|
||||
|
||||
file = open(args.moltofile, "r")
|
||||
|
||||
for line in file:
|
||||
if line != "\n":
|
||||
line_count += 1
|
||||
file.close()
|
||||
|
||||
# pylint: disable=no-member
|
||||
for otp in payload.otp_parameters:
|
||||
j += 1
|
||||
|
||||
if verbose: print('\n{}. Secret Key'.format(j))
|
||||
else: print()
|
||||
print('Name: {}'.format(otp.name))
|
||||
secret = convert_secret_from_bytes_to_base32_str(otp.secret)
|
||||
#print('Secret: {}'.format(secret))
|
||||
if otp.issuer: print('Issuer: {}'.format(otp.issuer))
|
||||
print('Type: {}'.format(get_enum_name_by_number(otp, 'type')))
|
||||
url_params = { 'secret': secret }
|
||||
if otp.type == 1: url_params['counter'] = otp.counter
|
||||
if otp.issuer: url_params['issuer'] = otp.issuer
|
||||
otp_url = 'otpauth://{}/{}?'.format('totp' if otp.type == 2 else 'hotp', quote(otp.name)) + urlencode(url_params)
|
||||
if args.moltofile:
|
||||
with open(args.moltofile, 'a') as f:
|
||||
#Create text file with seed info
|
||||
f.write(str(line_count+j)+' '+secret+' sha1 6 30 yes yes '+otp.issuer+'\n')
|
||||
if args.htmlfile:
|
||||
with open(args.htmlfile, 'a') as f2:
|
||||
#Create html file with seed info in QR format
|
||||
keyURI="otpauth://totp/"+otp.name+"?secret="+secret#+"?issuer="+otp.issuer
|
||||
#Generate QR code image
|
||||
system ("SimpleCodeGenerator.exe /Save "+ keyURI + " img/"+str(line_count+j)+".png")
|
||||
encoded = base64.b64encode(open("img/"+str(line_count+j)+".png", "rb").read())
|
||||
encoded2=encoded.decode('utf-8')
|
||||
remove("img/"+str(line_count+j)+".png")
|
||||
f2.write('TOTP Profile '+str(line_count+j)+':'+otp.name+"<br><img width=250 src='data:image/png;base64,"+encoded2+"'><pre>"+secret+"</pre><hr><br><br>")
|
||||
#empty input_qr.txt
|
||||
f = open('input_qr.txt', 'r+')
|
||||
f.truncate(0) # need '0' when using r+
|
||||
|
||||
print(' ')
|
||||
print('Files have been generated:')
|
||||
print (args.htmlfile)
|
||||
print (args.moltofile)
|
||||
@@ -0,0 +1,167 @@
|
||||
# Based on the original script from : Scito (https://scito.ch)
|
||||
# Changes in this script:
|
||||
# 1. Changed the QR code generation method to SimpleCodeGenerator from Nir Sofer
|
||||
# 2. Changed export format to have HTML and Molto-2 compatible import file
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import glob
|
||||
import subprocess
|
||||
from urllib.parse import parse_qs, urlencode, urlparse, quote
|
||||
from os import name, path, remove
|
||||
import generated_python.google_auth_pb2
|
||||
arg_parser = argparse.ArgumentParser()
|
||||
arg_parser.add_argument(
|
||||
'--verbose', '-v', help='verbose output', action='store_true')
|
||||
arg_parser.add_argument(
|
||||
'--saveqr', '-s', help='save QR code(s) as images to the "qr" subfolder', action='store_true')
|
||||
arg_parser.add_argument(
|
||||
'--printqr', '-p', help='print QR code(s) as text to the terminal', action='store_true')
|
||||
arg_parser.add_argument(
|
||||
'--infile', help='file or - for stdin (default: -) with "otpauth-migration://..." URLs separated by newlines, lines starting with # are ignored')
|
||||
arg_parser.add_argument(
|
||||
'--moltofile', help='save exctracted data in file compatible with Molto-2 format. If file does not exist a new file will be created.')
|
||||
arg_parser.add_argument(
|
||||
'--htmlfile', help='save exctracted data in html file with QR codes for enrolling TOTP profiles to other apps or single profile tokens')
|
||||
arg_parser.add_argument(
|
||||
'--fromimg', help='read otpauth-migration strings from a screenshot')
|
||||
args = arg_parser.parse_args()
|
||||
|
||||
verbose = args.verbose
|
||||
|
||||
# https://stackoverflow.com/questions/40226049/find-enums-listed-in-python-descriptor-for-protobuf
|
||||
|
||||
|
||||
def get_enum_name_by_number(parent, field_name):
|
||||
field_value = getattr(parent, field_name)
|
||||
return parent.DESCRIPTOR.fields_by_name[field_name].enum_type.values_by_number.get(field_value).name
|
||||
|
||||
|
||||
def convert_secret_from_bytes_to_base32_str(bytes):
|
||||
return str(base64.b32encode(otp.secret), 'utf-8').replace('=', '')
|
||||
|
||||
|
||||
def is_windows():
|
||||
return name == 'nt'
|
||||
|
||||
|
||||
# decode from image to text file
|
||||
if args.fromimg:
|
||||
if is_windows():
|
||||
qrscan = glob.glob('./qrscan/*/qrscan.exe', recursive=True)
|
||||
else:
|
||||
qrscan = glob.glob('./qrscan/*/qrscan', recursive=True)
|
||||
|
||||
if not qrscan:
|
||||
raise "Couldn't find qrscan, cant decode image"
|
||||
elif len(qrscan) > 1:
|
||||
raise "Multiple qrscans found, did you add one manually?"
|
||||
|
||||
if args.htmlfile:
|
||||
if path.exists(str(args.htmlfile)):
|
||||
remove(str(args.htmlfile))
|
||||
qrscan.append('--svg')
|
||||
qrscan.append(str(args.htmlfile))
|
||||
qrscan.append(str(args.fromimg))
|
||||
|
||||
otpauth_list = list()
|
||||
for line in subprocess.check_output(qrscan).splitlines():
|
||||
otpauth_list.append(line.decode("utf-8"))
|
||||
|
||||
print(type(otpauth_list))
|
||||
print(otpauth_list)
|
||||
for line in otpauth_list:
|
||||
print(f"line: {line}")
|
||||
|
||||
qr_as_image_base64 = base64.b64encode(
|
||||
open(str(args.htmlfile), "rb").read())
|
||||
qr_as_image_base64 = qr_as_image_base64.decode('utf-8')
|
||||
remove(str(args.htmlfile))
|
||||
|
||||
elif args.infile:
|
||||
otpauth_list = str(args.infile).splitlines()
|
||||
else:
|
||||
raise "Please provide either --infile or --fromimg as source"
|
||||
|
||||
i = j = 0
|
||||
print('Starting the process')
|
||||
for line in (line.strip() for line in otpauth_list):
|
||||
if verbose:
|
||||
print(line)
|
||||
if not line.startswith('otpauth-migration://'):
|
||||
print('\nWARN: line is not a otpauth-migration:// URL\ninput file: {}\nline "{}"\nProbably a wrong file was given'.format(otpauth_list, line))
|
||||
parsed_url = urlparse(line)
|
||||
params = parse_qs(parsed_url.query)
|
||||
if not 'data' in params:
|
||||
raise "result of qrscan looks invalid"
|
||||
data_encoded = params['data'][0]
|
||||
data = base64.b64decode(data_encoded)
|
||||
payload = generated_python.google_auth_pb2.MigrationPayload()
|
||||
payload.ParseFromString(data)
|
||||
i += 1
|
||||
if verbose:
|
||||
print('\n{}. Payload Line'.format(i), payload, sep='\n')
|
||||
line_count = -1
|
||||
# Count lines in Molto2-export.txt
|
||||
if args.moltofile:
|
||||
if path.exists(args.moltofile):
|
||||
|
||||
file = open(args.moltofile, "r")
|
||||
|
||||
for line in file:
|
||||
if line != "\n":
|
||||
line_count += 1
|
||||
file.close()
|
||||
|
||||
# pylint: disable=no-member
|
||||
for otp in payload.otp_parameters:
|
||||
j += 1
|
||||
|
||||
if verbose:
|
||||
print('\n{}. Secret Key'.format(j))
|
||||
else:
|
||||
print()
|
||||
print('Name: {}'.format(otp.name))
|
||||
secret = convert_secret_from_bytes_to_base32_str(otp.secret)
|
||||
# print('Secret: {}'.format(secret))
|
||||
if otp.issuer:
|
||||
print('Issuer: {}'.format(otp.issuer))
|
||||
print('Type: {}'.format(get_enum_name_by_number(otp, 'type')))
|
||||
url_params = {'secret': secret}
|
||||
if otp.type == 1:
|
||||
url_params['counter'] = otp.counter
|
||||
if otp.issuer:
|
||||
url_params['issuer'] = otp.issuer
|
||||
otp_url = 'otpauth://{}/{}?'.format('totp' if otp.type ==
|
||||
2 else 'hotp', quote(otp.name)) + urlencode(url_params)
|
||||
if args.moltofile:
|
||||
with open(args.moltofile, 'a') as f:
|
||||
# Create text file with seed info
|
||||
f.write(str(line_count+j)+' '+secret +
|
||||
' sha1 6 30 yes yes '+otp.issuer+'\n')
|
||||
if args.htmlfile:
|
||||
with open(args.htmlfile, 'a') as f2:
|
||||
# Create html file with seed info in QR format
|
||||
keyURI = "otpauth://totp/"+otp.name+"?secret="+secret # +"?issuer="+otp.issuer
|
||||
# Generate QR code image
|
||||
f2.write('TOTP Profile '+str(line_count+j)+':'+otp.name +
|
||||
"<br><img width=250 src='data:image/svg+xml;base64;utf-8,"+qr_as_image_base64+"'><pre>"+secret+"</pre><hr><br><br>")
|
||||
|
||||
print(' ')
|
||||
print('Files have been generated:')
|
||||
if args.htmlfile:
|
||||
print(args.htmlfile)
|
||||
if args.moltofile:
|
||||
print(args.moltofile)
|
||||
@@ -1 +0,0 @@
|
||||
this folder has to remain empty
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Executable
+29
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
(
|
||||
cd "$(dirname "$0")"
|
||||
version="${1:-0.1.6}"
|
||||
echo "Downloading version $version"
|
||||
|
||||
tools=(wget tar unzip)
|
||||
|
||||
tools_installed="true"
|
||||
for tool in "${tools[@]}"; do
|
||||
if ! which "$tool" &> /dev/null; then
|
||||
echo "please install $tool"
|
||||
tools_installed="false"
|
||||
fi
|
||||
done
|
||||
if ! "$tools_installed"; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
wget -O "qrscan-linux.tar.gz" "https://github.com/sayanarijit/qrscan/releases/download/v$version/qrscan-$version-x86_64-unknown-linux-gnu.tar.gz"
|
||||
tar --overwrite -xf "qrscan-linux.tar.gz"
|
||||
rm "qrscan-linux.tar.gz"
|
||||
wget -O "qrscan-windows.zip" "https://github.com/sayanarijit/qrscan/releases/download/v$version/qrscan-$version-x86_64-pc-windows-gnu.zip"
|
||||
unzip -o "qrscan-windows.zip"
|
||||
rm "qrscan-windows.zip"
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Arijit Basu
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,79 @@
|
||||
<h1 align="center">
|
||||
qrscan
|
||||
</h1>
|
||||
|
||||
<p align="center">
|
||||
Scan a QR code in the terminal using the system camera or a given image.
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
|
||||
<a href="https://crates.io/crates/qrscan">
|
||||
<img src="https://img.shields.io/crates/v/qrscan.svg" />
|
||||
</a>
|
||||
|
||||
<a href="https://github.com/sayanarijit/qrscan/commits">
|
||||
<img src="https://img.shields.io/github/commit-activity/m/sayanarijit/qrscan" />
|
||||
</a>
|
||||
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
|
||||
https://user-images.githubusercontent.com/11632726/178779071-ad5ca7da-0fc3-48c1-b725-a9834db39134.mp4
|
||||
|
||||
</p>
|
||||
|
||||
### Install
|
||||
|
||||
```bash
|
||||
cargo install --locked --force qrscan
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
Scan via the system camera with terminal preview
|
||||
|
||||
```bash
|
||||
qrscan --preview
|
||||
```
|
||||
|
||||
Scan a given image file
|
||||
|
||||
```bash
|
||||
qrscan path/to/file
|
||||
|
||||
# Or read from stdin
|
||||
|
||||
cat /path/to/file | qrscan -
|
||||
```
|
||||
|
||||
Print the QR code on the terminal
|
||||
|
||||
```bash
|
||||
qrscan <path/to/file> --qr --no-content
|
||||
```
|
||||
|
||||
Also print QR code metadata
|
||||
|
||||
```bash
|
||||
qrscan <path/to/file> --metadata
|
||||
```
|
||||
|
||||
Export the QR code as image files
|
||||
|
||||
```bash
|
||||
qrscan <path/to/file> --qr \
|
||||
--svg path/to/out.svg \
|
||||
--png path/to/out.png \
|
||||
--jpeg path/to/out.jpeg \
|
||||
--ascii path/to/out.ascii
|
||||
```
|
||||
|
||||
### Some Usage Examples
|
||||
|
||||
Capture a screenshot of a selected area using [ImageMagic](https://imagemagick.org/index.php) and scan the QR code.
|
||||
|
||||
```bash
|
||||
import png:- | qrscan -
|
||||
```
|
||||
Executable
BIN
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user