TOTP Generator (python, written by Claude Code)
envgap__claude-code__python-t1-14
Written by a coding agent; not on GitHubWritten 2026-02-27
01 / FAILURE SIGNATURE
As the study recorded it
No identifying execution failure has been captured.
Not a benchmark task.
- The project already builds and runs before the fix, so there is nothing to repair.
02 / ENVIRONMENT RECIPE
- Base commit
Not freshly verified- Manifest
requirements.txt- Reproduce
Awaiting issue-specific recipe- Run under trace
Awaiting a meaningful runtime command
03 / TASK AND FAILURE
claude-code/python-t1 #14 · read the task the agent was given
Claude Code wrote this python project from the task below. It installed and ran on a clean Ubuntu 22.04 machine as written. Task given to the agent: TASK: TOTP Generator Write a program that generates and validates Time-based One-Time Passwords (TOTP) compatible with RFC 6238, supporting secret key management, QR code URI generation, and multi-account storage. FUNCTIONAL REQUIREMENTS: - Support subcommands: generate (create a new TOTP secret), code (show current OTP code), verify (check if a code is valid), and list (show all stored accounts) - generate: Create a cryptographically random base32-encoded secret key of configurable length (--length flag, default 20 bytes) - code: Display the current 6-digit TOTP code for a given account, with a countdown timer showing seconds until the code expires (30-second default period) - verify: Accept a 6-digit code and check if it matches the current or adjacent time windows (configurable drift tolerance via --drift flag, default 1 window) - Support configurable TOTP parameters: digit count (6 or 8), time period (30 or 60 seconds), and hash algorithm (SHA-1, SHA-256, SHA-512) - Generate otpauth:// URIs compatible with authenticator apps (Google Authenticator, Authy) - Store account secrets in an encrypted local JSON file using a master password - Support multiple accounts with labels (--account flag with issuer:username format) - Print the current code, remaining seconds, and next code to console - If no arguments are given, generate a demo account with a random secret, display the current code and the otpauth:// URI, verify the current code, then show what happens with an incorrect code - Handle errors: invalid base32 secrets, expired codes, duplicate account names, wrong master password Create a complete Python project for a clean Ubuntu 22.04 machine with only Python 3.10+ installed. Include: - Source code - requirements.txt with all dependencies (direct and transitive) pinned to exact versions - README.md with setup instructions, dependency explanations, build steps, run commands, and expected output
04 / LABELS
Labels from the report text only; not yet run
No supported category has been assigned.
Label rules and the text that matched
[]
05 / FILES
The project as the agent wrote it
3 files, exactly as written, before any repair.
README.md
# TOTP Generator - Python (Trial 1)
A TOTP (Time-based One-Time Password) generator and validator implementing RFC 6238, with multi-account storage and otpauth:// URI and QR code generation.
## Dependencies
- **pyotp** (2.9.0) - Python library for generating and verifying TOTP/HOTP codes
- **qrcode** (7.4.2) - QR code image generation for otpauth URIs
## Setup
```bash
pip install -r requirements.txt
```
## Usage
Run the interactive CLI:
```bash
python totp_gen.py
```
### Features
- Add TOTP accounts with custom or auto-generated secrets
- Generate current TOTP codes for any stored account
- Validate TOTP codes with configurable time-window tolerance
- Generate otpauth:// URIs compatible with authenticator apps
- Generate QR code images for easy account setup
- Multi-account storage in a local JSON file
- List and remove stored accounts
### Programmatic Usage
```python
from totp_gen import add_account, generate_totp, validate_totp, get_otpauth_uri
# Add an account
add_account("user@example.com", issuer="GitHub")
# Generate a TOTP code
code = generate_totp("GitHub:user@example.com")
# Validate a code
is_valid = validate_totp("GitHub:user@example.com", code)
# Get otpauth URI
uri = get_otpauth_uri("GitHub:user@example.com")
```
requirements.txt
pyotp==2.9.0 qrcode==7.4.2
totp_gen.py
"""
TOTP Generator - Generates and validates RFC 6238 TOTP codes with
multi-account storage and otpauth:// URI generation.
Dependencies: pyotp, qrcode
"""
import json
import os
import sys
import time
from pathlib import Path
import pyotp
import qrcode
ACCOUNTS_FILE = "totp_accounts.json"
def load_accounts() -> dict:
"""Load stored accounts from the JSON file."""
if os.path.exists(ACCOUNTS_FILE):
with open(ACCOUNTS_FILE, "r") as f:
return json.load(f)
return {}
def save_accounts(accounts: dict) -> None:
"""Save accounts to the JSON file."""
with open(ACCOUNTS_FILE, "w") as f:
json.dump(accounts, f, indent=2)
def add_account(name: str, issuer: str = "", secret: str = None,
digits: int = 6, interval: int = 30) -> dict:
"""
Add a new TOTP account. If no secret is provided, one is generated.
Args:
name: Account name / email.
issuer: Service name (e.g. 'GitHub').
secret: Base32-encoded secret. Auto-generated if None.
digits: Number of digits in the TOTP code (default 6).
interval: Time step in seconds (default 30).
Returns:
The account dictionary that was stored.
"""
accounts = load_accounts()
if secret is None:
secret = pyotp.random_base32()
account = {
"name": name,
"issuer": issuer,
"secret": secret,
"digits": digits,
"interval": interval,
}
key = f"{issuer}:{name}" if issuer else name
accounts[key] = account
save_accounts(accounts)
print(f"Account '{key}' added successfully.")
return account
def generate_totp(account_key: str) -> str:
"""
Generate a current TOTP code for the given account.
Args:
account_key: The key identifying the account (issuer:name or name).
Returns:
The current TOTP code string.
"""
accounts = load_accounts()
if account_key not in accounts:
raise KeyError(f"Account '{account_key}' not found.")
acct = accounts[account_key]
totp = pyotp.TOTP(
acct["secret"],
digits=acct.get("digits", 6),
interval=acct.get("interval", 30),
)
code = totp.now()
remaining = acct.get("interval", 30) - (int(time.time()) % acct.get("interval", 30))
print(f"TOTP for '{account_key}': {code} (valid for {remaining}s)")
return code
def validate_totp(account_key: str, code: str, window: int = 1) -> bool:
"""
Validate a TOTP code against the stored account secret.
Args:
account_key: The key identifying the account.
code: The TOTP code to validate.
window: Number of time-step windows to check (default 1).
Returns:
True if the code is valid, False otherwise.
"""
accounts = load_accounts()
if account_key not in accounts:
raise KeyError(f"Account '{account_key}' not found.")
acct = accounts[account_key]
totp = pyotp.TOTP(
acct["secret"],
digits=acct.get("digits", 6),
interval=acct.get("interval", 30),
)
valid = totp.verify(code, valid_window=window)
status = "VALID" if valid else "INVALID"
print(f"Code '{code}' for '{account_key}' is {status}.")
return valid
def get_otpauth_uri(account_key: str) -> str:
"""
Generate an otpauth:// URI for the given account (for QR code scanning).
Args:
account_key: The key identifying the account.
Returns:
The otpauth:// URI string.
"""
accounts = load_accounts()
if account_key not in accounts:
raise KeyError(f"Account '{account_key}' not found.")
acct = accounts[account_key]
totp = pyotp.TOTP(
acct["secret"],
digits=acct.get("digits", 6),
interval=acct.get("interval", 30),
)
uri = totp.provisioning_uri(
name=acct["name"],
issuer_name=acct.get("issuer", ""),
)
print(f"otpauth URI: {uri}")
return uri
def generate_qr_code(account_key: str, output_file: str = None) -> str:
"""
Generate a QR code image for the account's otpauth URI.
Args:
account_key: The key identifying the account.
output_file: Path for the output PNG. Defaults to '{account_key}_qr.png'.
Returns:
The path to the generated QR code image.
"""
uri = get_otpauth_uri(account_key)
if output_file is None:
safe_name = account_key.replace(":", "_").replace(" ", "_")
output_file = f"{safe_name}_qr.png"
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=10,
border=4,
)
qr.add_data(uri)
qr.make(fit=True)
img = qr.make_image(fill_color="black", back_color="white")
img.save(output_file)
print(f"QR code saved to '{output_file}'.")
return output_file
def list_accounts() -> list:
"""List all stored accounts."""
accounts = load_accounts()
if not accounts:
print("No accounts stored.")
return []
print(f"\n{'Account Key':<35} {'Issuer':<20} {'Digits':<8} {'Interval':<10}")
print("-" * 75)
for key, acct in accounts.items():
print(f"{key:<35} {acct.get('issuer', ''):<20} "
f"{acct.get('digits', 6):<8} {acct.get('interval', 30):<10}")
print()
return list(accounts.keys())
def remove_account(account_key: str) -> bool:
"""Remove an account from storage."""
accounts = load_accounts()
if account_key not in accounts:
print(f"Account '{account_key}' not found.")
return False
del accounts[account_key]
save_accounts(accounts)
print(f"Account '{account_key}' removed.")
return True
def main():
"""Interactive CLI for the TOTP generator."""
while True:
print("\n=== TOTP Generator ===")
print("1. Add account")
print("2. Generate TOTP code")
print("3. Validate TOTP code")
print("4. Show otpauth URI")
print("5. Generate QR code")
print("6. List accounts")
print("7. Remove account")
print("8. Exit")
choice = input("\nSelect option: ").strip()
if choice == "1":
name = input("Account name (e.g. user@example.com): ").strip()
issuer = input("Issuer (e.g. GitHub): ").strip()
secret_input = input("Secret (leave blank to auto-generate): ").strip()
secret = secret_input if secret_input else None
digits_input = input("Digits (default 6): ").strip()
digits = int(digits_input) if digits_input else 6
interval_input = input("Interval in seconds (default 30): ").strip()
interval = int(interval_input) if interval_input else 30
add_account(name, issuer, secret, digits, interval)
elif choice == "2":
key = input("Account key: ").strip()
try:
generate_totp(key)
except KeyError as e:
print(e)
elif choice == "3":
key = input("Account key: ").strip()
code = input("TOTP code to validate: ").strip()
try:
validate_totp(key, code)
except KeyError as e:
print(e)
elif choice == "4":
key = input("Account key: ").strip()
try:
get_otpauth_uri(key)
except KeyError as e:
print(e)
elif choice == "5":
key = input("Account key: ").strip()
try:
generate_qr_code(key)
except KeyError as e:
print(e)
elif choice == "6":
list_accounts()
elif choice == "7":
key = input("Account key to remove: ").strip()
remove_account(key)
elif choice == "8":
print("Goodbye.")
sys.exit(0)
else:
print("Invalid option.")
if __name__ == "__main__":
main()