going-flying.com gemini git repository
ae879fbe5902b4951c86b1da630e7dabc2015c13 - Matthew Ernisse - 1612636964
totp qr creator!
diff --git a/cgi-bin/converter b/cgi-bin/converter index 9a4b843..7aaf40d 100755 --- a/cgi-bin/converter +++ b/cgi-bin/converter @@ -29,7 +29,9 @@ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ''' import base64 import os +import secrets import sys +import qrcode from urllib.parse import parse_qs, quote, unquote, urlparse @@ -54,6 +56,10 @@ Display a number in binary, decimal and hexadecimal. If your input cannot be re => url/encode URL Quote => url/decode URL Unquote +## Random Stuff + +=> random/base32 Random BASE32 secret + ## Suggestions? Want to see something here? Feel free to drop me a line. => mailto:matt@going-flying.com @@ -130,10 +136,13 @@ class GeminiCGI(object): -def encode_response(input, result): +def encode_response(cgi, input, result): global BACK_LINK cgi.Response.Ok('text/gemini') + if type(result) == bytes: + result = result.decode('utf-8') + output = f'# Input\n{input}\n\n' output += f'# Output\n{result}\n\n' output += f'=> {BACK_LINK} Back\n' @@ -181,6 +190,25 @@ def result_table(cgi, input, b, d, h): print(output) +def secret_response(cgi, val, qr=False): + global BACK_LINK + cgi.Response.Ok('text/gemini') + + if type(val) == bytes: + val = val.decode('utf-8') + + output = f'# Your secret\n' + output += f'{val}\n' + + if qr: + e_val = base64.b64encode(val.encode('utf-8')).decode('utf-8') + output += f'=> {BACK_LINK}random/qr/{e_val}\n\n' + + output += f'=> {BACK_LINK} Back\n' + output += f'=> / Home' + print(output) + + if __name__ == '__main__': cgi = GeminiCGI() @@ -213,6 +241,25 @@ if __name__ == '__main__': elif cgi.path_info == 'url/decode': cgi.Response.Input('String to decode?') + # Random Stuff + elif cgi.path_info == 'random/base32': + val = base64.b32encode(secrets.token_bytes(30)) + secret_response(cgi, val) + + elif cgi.path_info == 'random/totp': + cgi.Response.Input('Account Label?') + + elif cgi.path_info.startswith('random/qr'): + val = cgi.path_info.split('/')[-1] + val = base64.b64decode(val).decode('utf-8') + cgi.Response.Ok('image/png') + png = qrcode.make(val) + + sys.stdout.flush() + png.save(sys.stdout.buffer) + + else: + cgi.Response.Redirect(BACK_LINK) else: if not cgi.path_info: cgi.Response.Redirect(BACK_LINK) @@ -262,25 +309,23 @@ if __name__ == '__main__': s = cgi.query_dequoted try: res = base64.b64encode(s.encode('utf-8')) - res = res.decode('utf-8') except Exception as e: sys.stderr.write(f'{e!s}\n') sys.stderr.flush() cgi.Response.Fail() sys.exit() - encode_response(s, res) + encode_response(cgi, s, res) elif cgi.path_info == 'base64/decode': s = cgi.query_dequoted try: res = base64.b64decode(s, validate=True) - res = res.decode('utf-8') except Exception: cgi.Response.Fail() sys.exit() - encode_response(s, res) + encode_response(cgi, s, res) # urlencode/decode elif cgi.path_info == 'url/encode': @@ -291,7 +336,7 @@ if __name__ == '__main__': cgi.Response.Fail() sys.exit() - encode_response(s, res) + encode_response(cgi, s, res) elif cgi.path_info == 'url/decode': s = cgi.query_dequoted @@ -301,7 +346,19 @@ if __name__ == '__main__': cgi.Response.Fail() sys.exit() - encode_response(s, res) + encode_response(cgi, s, res) + + # Random Stuff + elif cgi.path_info == 'random/totp': + # Leave pre-urlencoded! + label = cgi.query_string + val = base64.b32encode(secrets.token_bytes(30)) + val = val.decode('utf-8') + secret_response( + cgi, + f'otpauth://totp/{label}?secret={val}', + True + ) else: cgi.Response.NotFound()