mirror of
https://github.com/scito/extract_otp_secret_keys.git
synced 2025-12-06 14:54:57 +01:00
Option to save QR codes as PNG (#2)
* Generate QR code images Now generates QR images instead of attempting to display the QR code in the console. Places them in a subdirectory of the current directory, entitled "qr" * Update README.md * Changes based on suggestions from scito https://github.com/scito/extract_otp_secret_keys/pull/2#pullrequestreview-555264890 * Update extract_otp_secret_keys.py Minor formatting changes and clarifications to help text * Update extract_otp_secret_keys.py Remove --qr argument, instead opting to respond to --printqr or --saveqr
This commit is contained in:
parent
6068eb142c
commit
cc26f7b589
2 changed files with 27 additions and 5 deletions
|
|
@ -21,7 +21,7 @@ The protobuf package of Google for proto3 is required for running this script.
|
||||||
|
|
||||||
For printing QR codes, the qrcode module is required
|
For printing QR codes, the qrcode module is required
|
||||||
|
|
||||||
pip install qrcode
|
pip install qrcode[pil]
|
||||||
|
|
||||||
## Technical background
|
## Technical background
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,17 +46,22 @@ import base64
|
||||||
import fileinput
|
import fileinput
|
||||||
import sys
|
import sys
|
||||||
from urllib.parse import parse_qs, urlencode, urlparse, quote
|
from urllib.parse import parse_qs, urlencode, urlparse, quote
|
||||||
|
from os import path, mkdir
|
||||||
|
from re import sub, compile as rcompile
|
||||||
import generated_python.google_auth_pb2
|
import generated_python.google_auth_pb2
|
||||||
|
|
||||||
arg_parser = argparse.ArgumentParser()
|
arg_parser = argparse.ArgumentParser()
|
||||||
arg_parser.add_argument('--verbose', '-v', help='verbose output', action='store_true')
|
arg_parser.add_argument('--verbose', '-v', help='verbose output', action='store_true')
|
||||||
arg_parser.add_argument('--qr', '-q', help='print QR codes (otpauth://...)', 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('infile', help='file or - for stdin (default: -) with "otpauth-migration://..." URLs separated by newlines, lines starting with # are ignored')
|
||||||
args = arg_parser.parse_args()
|
args = arg_parser.parse_args()
|
||||||
|
|
||||||
verbose = args.verbose
|
verbose = args.verbose
|
||||||
if args.qr:
|
saveqr = args.saveqr
|
||||||
|
printqr = args.printqr
|
||||||
|
|
||||||
|
if saveqr or printqr:
|
||||||
from qrcode import QRCode
|
from qrcode import QRCode
|
||||||
|
|
||||||
# https://stackoverflow.com/questions/40226049/find-enums-listed-in-python-descriptor-for-protobuf
|
# https://stackoverflow.com/questions/40226049/find-enums-listed-in-python-descriptor-for-protobuf
|
||||||
|
|
@ -68,6 +73,13 @@ def convert_secret_from_bytes_to_base32_str(bytes):
|
||||||
return str(base64.b32encode(otp.secret), 'utf-8').replace('=', '')
|
return str(base64.b32encode(otp.secret), 'utf-8').replace('=', '')
|
||||||
|
|
||||||
|
|
||||||
|
def save_qr(data, name):
|
||||||
|
qr = QRCode()
|
||||||
|
qr.add_data(data)
|
||||||
|
img = qr.make_image(fill_color="black", back_color="white")
|
||||||
|
if verbose: print("Saving to {}".format(name))
|
||||||
|
img.save(name)
|
||||||
|
|
||||||
def print_qr(data):
|
def print_qr(data):
|
||||||
qr = QRCode()
|
qr = QRCode()
|
||||||
qr.add_data(data)
|
qr.add_data(data)
|
||||||
|
|
@ -85,7 +97,9 @@ for line in (line.strip() for line in fileinput.input(args.infile)):
|
||||||
if verbose: print(payload)
|
if verbose: print(payload)
|
||||||
|
|
||||||
# pylint: disable=no-member
|
# pylint: disable=no-member
|
||||||
|
i = 0
|
||||||
for otp in payload.otp_parameters:
|
for otp in payload.otp_parameters:
|
||||||
|
i += 1
|
||||||
print('\nName: {}'.format(otp.name))
|
print('\nName: {}'.format(otp.name))
|
||||||
secret = convert_secret_from_bytes_to_base32_str(otp.secret)
|
secret = convert_secret_from_bytes_to_base32_str(otp.secret)
|
||||||
print('Secret: {}'.format(secret))
|
print('Secret: {}'.format(secret))
|
||||||
|
|
@ -95,6 +109,14 @@ for line in (line.strip() for line in fileinput.input(args.infile)):
|
||||||
if otp.type == 1: url_params['counter'] = otp.counter
|
if otp.type == 1: url_params['counter'] = otp.counter
|
||||||
if otp.issuer: url_params['issuer'] = otp.issuer
|
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)
|
otp_url = 'otpauth://{}/{}?'.format('totp' if otp.type == 2 else 'hotp', quote(otp.name)) + urlencode(url_params)
|
||||||
if args.qr:
|
if saveqr:
|
||||||
|
if verbose: print(otp_url)
|
||||||
|
if not(path.exists("qr")): mkdir("qr")
|
||||||
|
pattern = rcompile('[\W_]+')
|
||||||
|
file_otp_name = pattern.sub('', otp.name)
|
||||||
|
file_otp_issuer = pattern.sub('', otp.issuer)
|
||||||
|
if not(file_otp_issuer): print_qr(otp_url, "qr/{}-{}.png".format(i, file_otp_name))
|
||||||
|
if file_otp_issuer: save_qr(otp_url, "qr/{}-{}-{}.png".format(i,file_otp_name, file_otp_issuer))
|
||||||
|
if printqr:
|
||||||
if verbose: print(otp_url)
|
if verbose: print(otp_url)
|
||||||
print_qr(otp_url)
|
print_qr(otp_url)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue