From: Jorge Pereira Date: Thu, 14 Sep 2023 03:19:28 +0000 (-0300) Subject: totp: Add scripts/totp/totp-gen.py sample X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=de886bc050a5e62e749198b02695d2da1df077bd;p=thirdparty%2Ffreeradius-server.git totp: Add scripts/totp/totp-gen.py sample It's helpful to validate rlm_totp in realtime. --- diff --git a/scripts/totp/totp-gen.py b/scripts/totp/totp-gen.py new file mode 100755 index 00000000000..bd3b65b8fae --- /dev/null +++ b/scripts/totp/totp-gen.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# Author: Jorge Pereira +# Simple TOTP generator. + +import argparse +import base64 +import hmac +import struct +import sys +import time + +def hotp(key, counter, digits=6, digest='sha1'): + key = key.encode('ascii') + counter = struct.pack('>Q', counter) + mac = hmac.new(key, counter, digest).digest() + offset = mac[-1] & 0x0f + binary = struct.unpack('>L', mac[offset:offset+4])[0] & 0x7fffffff + return str(binary)[-digits:].zfill(digits) + +def totp(key, time_step=30, digits=6, digest='sha1'): + return hotp(key, int(time.time() / time_step), digits, digest) + +def main(): + parser = argparse.ArgumentParser(description = "Simple TOTP token generator.") + parser.add_argument("-k", dest = "key", help = "Key in raw format.", required = True) + parser.add_argument("-t", dest = "time_step", help = "time step between time changes.", default = 30, type = int) + parser.add_argument("-d", dest = "digits", help = "Length of the one-time password.", default = 6, type = int) + parser.add_argument("-e", dest = "encode_base32", help = "Encode the output token in base32.", action='store_true') + parser.add_argument("-D", dest = "digest", help = "HMAC algorithm as described by RFC 2104. default: sha1, options: sha1, sha256, sha512", required = False, default = "sha1") + args = parser.parse_args() + token = totp(args.key, args.time_step, args.digits, args.digest) + + if args.encode_base32: + token = base64.b32encode(bytearray(token, 'ascii')).decode('ascii') + + print(token) + +if __name__ == '__main__': + main()