Files
KNELAgentIdentityProvisioning/skills/agent-provisioning/scripts/totp.sh
T
TSYS Group COO bde7845490 skills: agent-provisioning - codified identity stand-up workflow
Policy rulings (#942): unique passwords, Cloudron-only SSO accounts,
no reachableceo credentials, TOTP seeds MUST be captured to the vault.
Cloudron admin API wrapper, cookie-jar OIDC login, RFC-6238-tested
TOTP helper, per-system SSO/API references, incident log.
2026-09-08 04:07:14 -05:00

21 lines
1.0 KiB
Bash
Executable File

#!/bin/bash
# Current TOTP code from a base32 seed (pure bash + openssl + coreutils).
# usage: totp.sh <base32-seed> [step-seconds] [digits]
set -euo pipefail
SECRET="${1:?usage: totp.sh <base32-seed> [step] [digits]}"
STEP="${2:-30}"; DIGITS="${3:-6}"
NOW="${TOTP_NOW:-$(date +%s)}" # TOTP_NOW: RFC-6238 test vector override
KEYHEX=$(printf '%s' "$SECRET" | tr -d ' =\n-' | base32 -d 2>/dev/null | od -An -tx1 | tr -d ' \n')
[ -n "$KEYHEX" ] || { echo "bad base32 seed" >&2; exit 2; }
COUNTER=$(printf '%016x' $(( NOW / STEP )))
# bash vars cannot hold null bytes - keep the counter as a FORMAT string and
# let printf emit the raw bytes straight into the pipe.
FMT=$(printf '%s' "$COUNTER" | sed 's/../\\x&/g')
# intentional: FMT emits raw counter bytes incl. NULs - the whole point
# shellcheck disable=SC2059
MAC=$(printf "$FMT" | openssl dgst -sha1 -mac HMAC -macopt "hexkey:$KEYHEX" -binary \
| od -An -tx1 | tr -d ' \n')
OFFSET=$(( 0x${MAC: -1} ))
CODE=$(( (0x${MAC:$((OFFSET*2)):8} & 0x7fffffff) % (10 ** DIGITS) ))
printf "%0${DIGITS}d\n" "$CODE"