bettertotp 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Shri Kant
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,685 @@
1
+ Metadata-Version: 2.4
2
+ Name: bettertotp
3
+ Version: 0.2.0
4
+ Summary: A TOTP-based time-varying code generator with alphanumeric and special character output
5
+ Author-email: Shri Kant <skjaimini9@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/skjaimini9/bettertotp
8
+ Project-URL: Repository, https://github.com/skjaimini9/bettertotp
9
+ Project-URL: Bug Tracker, https://github.com/skjaimini9/bettertotp/issues
10
+ Keywords: totp,2fa,authentication,security,one-time-password,hmac,sha512
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: End Users/Desktop
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Security :: Cryptography
22
+ Classifier: Topic :: Utilities
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: cryptography
27
+ Provides-Extra: clipboard
28
+ Requires-Dist: pyperclip; extra == "clipboard"
29
+ Provides-Extra: qr
30
+ Requires-Dist: qrcode[pil]; extra == "qr"
31
+ Provides-Extra: completion
32
+ Requires-Dist: argcomplete; extra == "completion"
33
+ Provides-Extra: all
34
+ Requires-Dist: bettertotp[clipboard]; extra == "all"
35
+ Requires-Dist: bettertotp[qr]; extra == "all"
36
+ Requires-Dist: bettertotp[completion]; extra == "all"
37
+ Dynamic: license-file
38
+
39
+ # BetterTOTP
40
+
41
+ [![Python](https://img.shields.io/badge/python-3.10%2B-blue)](https://python.org)
42
+ [![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
43
+ [![Android](https://img.shields.io/badge/Android-3DDC84?logo=android&logoColor=white)](android/)
44
+ [![Linux](https://img.shields.io/badge/Linux-FCC624?logo=linux&logoColor=black)](linux/)
45
+ [![API](https://img.shields.io/badge/API-FastAPI-009688?logo=fastapi&logoColor=white)](web/)
46
+
47
+ A TOTP-based time-varying code generator with alphanumeric and special character output. Uses HMAC-SHA512 (or SHA1/SHA256) to produce 12-character codes (configurable length) from a 75-character alphabet (`A-Z a-z 0-9 !@#$%&*-_+=?~`), with an encrypted vault for storing secrets. A native Android app is available in `android/`, and a standalone Linux binary in `linux/`.
48
+
49
+ ---
50
+
51
+ ## Features
52
+
53
+ - **Configurable TOTP** — Choose hash algorithm (SHA1, SHA256, SHA512), code length, and time step
54
+ - **Encrypted vault** — Store multiple named secrets in `~/.config/btotp/vault.json` encrypted with AES-256-GCM (PBKDF2-derived key from master password)
55
+ - **otpauth URI support** — Import accounts from standard `otpauth://totp/...` URIs (compatible with Bitwarden, Authy, Google Authenticator, etc.)
56
+ - **QR code display** — Render QR codes directly in the terminal for mobile enrollment
57
+ - **Clipboard copy** — Copy codes to clipboard (supports pyperclip, xclip, xsel, pbcopy)
58
+ - **Shell completions** — Generate tab-completion scripts for bash, zsh, and fish
59
+ - **Export/Import vault** — JSON-based backup and restore
60
+ - **User config** — Persistent defaults via `~/.config/btotp/config.json`
61
+ - **Android app** — Native Kotlin app with Master Password or Biometric vault modes, Material 3 UI
62
+ - **Linux binary** — Standalone executable (no Python needed), Tkinter GUI if available, CLI fallback, registers as `otpauth://` handler
63
+ - **Web API** — FastAPI microservice for TOTP enrollment and verification, stateless, ready to integrate into any website backend
64
+
65
+ ---
66
+
67
+ ## Installation
68
+
69
+ ```bash
70
+ pip install bettertotp
71
+
72
+ # Optional feature groups:
73
+ pip install bettertotp[clipboard] # clipboard support (pyperclip)
74
+ pip install bettertotp[qr] # QR code display
75
+ pip install bettertotp[completion] # shell tab-completion
76
+ pip install bettertotp[all] # all optional features
77
+ ```
78
+
79
+ ### From source
80
+
81
+ ```bash
82
+ git clone https://github.com/skjaimini9/bettertotp.git
83
+ cd bettertotp
84
+ pip install .
85
+ ```
86
+
87
+ ### Android app
88
+
89
+ Build the native Android APK from the `android/` directory:
90
+
91
+ ```bash
92
+ # 1. Generate a signing keystore (one-time)
93
+ keytool -genkey -v -keystore ~/.android/bettertotp-release.jks \
94
+ -alias bettertotp -keyalg RSA -keysize 2048 -validity 10000
95
+
96
+ # 2. Install Android SDK and set ANDROID_HOME
97
+
98
+ # 3. Download the Gradle wrapper
99
+ cd android
100
+ gradle wrapper
101
+
102
+ # 4. Build the release APK
103
+ BTOTP_KEYSTORE_PATH=~/.android/bettertotp-release.jks \
104
+ BTOTP_STORE_PASSWORD=your-keystore-password \
105
+ BTOTP_KEY_ALIAS=bettertotp \
106
+ BTOTP_KEY_PASSWORD=your-key-password \
107
+ ./gradlew assembleRelease
108
+
109
+ # 5. Locate the signed APK
110
+ ls app/build/outputs/apk/release/app-release.apk
111
+
112
+ # 6. GPG-sign the APK for distribution
113
+ gpg --detach-sign --armor app/build/outputs/apk/release/app-release.apk
114
+ ```
115
+
116
+ The Android app is a native Kotlin + Jetpack Compose application with two vault modes:
117
+ - **Master Password** — PBKDF2 + AES-256-GCM (identical algorithm to the CLI version)
118
+ - **Biometric** — Android Keystore-backed, unlocks with fingerprint or device PIN
119
+
120
+ ### Linux binary
121
+
122
+ Build the standalone executable from the `linux/` directory:
123
+
124
+ ```bash
125
+ # 1. Generate a GPG signing key (one-time, if signing releases)
126
+ gpg --full-generate-key
127
+
128
+ # 2. Install dependencies
129
+ pip install pyinstaller cryptography
130
+
131
+ # 3. Build the binary and release archive
132
+ cd linux
133
+ chmod +x build.sh
134
+ ./build.sh
135
+
136
+ # 4. Locate the outputs
137
+ ls dist/btotp # single-file binary
138
+ ls dist/btotp-linux-x86_64.tar.gz # release archive
139
+ ```
140
+
141
+ The binary works on any Linux distro with glibc ≥ 2.28 (Debian 10+, Ubuntu 18.04+, Fedora 30+, Arch). It adapts to your environment:
142
+
143
+ - **With a display** → Tkinter GUI window (unlock → live code list → add/copy/delete)
144
+ - **Without a display** → Falls back to the CLI (same as `btotp` from pip)
145
+ - **`btotp otpauth://totp/...`** → Imports the URI directly (GUI or CLI)
146
+ - **Register as URI handler** → `./register-handler.sh` enables one-click import from a browser
147
+
148
+ ### Web backend API
149
+
150
+ A stateless FastAPI microservice for integrating BetterTOTP into any website backend.
151
+
152
+ ```bash
153
+ # 1. Install dependencies
154
+ cd web
155
+ pip install -r requirements.txt
156
+
157
+ # 2. Start the server
158
+ uvicorn main:app --host 0.0.0.0 --port 8000
159
+
160
+ # 3. Enroll a new user
161
+ curl -X POST http://localhost:8000/api/enroll \
162
+ -H "Content-Type: application/json" \
163
+ -d '{"account": "user@example.com", "issuer": "MyApp"}'
164
+
165
+ # 4. Verify a TOTP code at login
166
+ curl -X POST http://localhost:8000/api/verify \
167
+ -H "Content-Type: application/json" \
168
+ -d '{"secret_hex": "<from step 3>", "code": "<user typed>"}'
169
+ ```
170
+
171
+ **Integration flow:**
172
+ 1. User enables 2FA → `POST /api/enroll` → store `secret_hex` in your DB → render QR from `uri`
173
+ 2. User logs in → `POST /api/verify` with the stored `secret_hex` → if `valid: true`, allow access
174
+
175
+ The API is stateless — your backend owns the secret storage. See `web/README.md` for full documentation.
176
+
177
+ ---
178
+
179
+ ## Quick Start
180
+
181
+ ### 1. Create a vault
182
+
183
+ ```bash
184
+ btotp init
185
+ ```
186
+
187
+ You'll be prompted for a master password. This creates `~/.config/btotp/vault.json`.
188
+
189
+ ### 2. Add an account
190
+
191
+ ```bash
192
+ # Generate a random secret:
193
+ btotp add my-account --generate
194
+
195
+ # Or provide an existing hex secret:
196
+ btotp add my-account -s "a1b2c3d4..."
197
+
198
+ # Or import from an otpauth:// URI:
199
+ btotp import-uri "otpauth://totp/Example:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=Example"
200
+
201
+ # Or provide a base32 secret:
202
+ btotp add my-account --b32 "JBSWY3DPEHPK3PXP"
203
+ ```
204
+
205
+ ### 3. Get a code
206
+
207
+ ```bash
208
+ btotp code -a my-account
209
+ ```
210
+
211
+ ### 4. List all accounts
212
+
213
+ ```bash
214
+ btotp list
215
+ ```
216
+
217
+ Output:
218
+ ```
219
+ my-account 3vMU-DiSZn0n (12c / 45s)
220
+ github W078kA**ytRu (12c / 45s)
221
+ ```
222
+
223
+ ---
224
+
225
+ ## CLI Reference
226
+
227
+ ### `btotp generate-secret`
228
+
229
+ Generate a new random secret key (64 bytes by default).
230
+
231
+ ```
232
+ btotp generate-secret [-o FILE] [-f {hex,b32}]
233
+ ```
234
+
235
+ | Flag | Description |
236
+ |---|---|
237
+ | `-o, --output` | Write secret to file instead of stdout |
238
+ | `-f, --format` | Output format: `hex` (default, chunked) or `b32` |
239
+
240
+ ### `btotp code`
241
+
242
+ Generate a TOTP code from a secret or vault account.
243
+
244
+ ```
245
+ btotp code [-s SECRET | -a ACCOUNT] [-w] [--copy] [--algo ALGO] [--length N] [--step N]
246
+ ```
247
+
248
+ | Flag | Description |
249
+ |---|---|
250
+ | `-s, --secret` | Secret key as a hex string |
251
+ | `-a, --account` | Account name in the vault |
252
+ | `-w, --watch` | Watch mode — refresh periodically (press Ctrl+C to stop) |
253
+ | `--copy` | Copy the code to clipboard instead of stdout |
254
+ | `--algo, --algorithm` | Hash algorithm: `sha1`, `sha256`, `sha512` (default: `sha512`) |
255
+ | `--length` | Code length in characters (default: 12) |
256
+ | `--step` | Time step in seconds (default: 45) |
257
+
258
+ ### `btotp verify`
259
+
260
+ Verify a TOTP code against a secret or vault account.
261
+
262
+ ```
263
+ btotp verify (-s SECRET | -a ACCOUNT) -c CODE [-n WINDOW] [--algo ALGO] [--length N] [--step N]
264
+ ```
265
+
266
+ | Flag | Description |
267
+ |---|---|
268
+ | `-s, --secret` | Secret key as a hex string |
269
+ | `-a, --account` | Account name in the vault |
270
+ | `-c, --code` | Code to verify |
271
+ | `-n, --window` | Time drift window (default: 1 step in each direction) |
272
+ | `--algo, --algorithm` | Hash algorithm |
273
+ | `--length` | Code length |
274
+ | `--step` | Time step |
275
+
276
+ Exits with status 0 if valid, 1 if invalid.
277
+
278
+ ### `btotp init`
279
+
280
+ Create a new encrypted vault.
281
+
282
+ ```
283
+ btotp init
284
+ ```
285
+
286
+ Prompts for a master password (and confirmation). Creates `~/.config/btotp/vault.json`.
287
+
288
+ ### `btotp add`
289
+
290
+ Add an account to the vault.
291
+
292
+ ```
293
+ btotp add NAME [-s SECRET] [--b32 B32] [-u URI] [-g] [-i ISSUER] [--algo ALGO] [--digits N] [--period N]
294
+ ```
295
+
296
+ | Argument | Description |
297
+ |---|---|
298
+ | `NAME` | Account name (required) |
299
+ | `-s, --secret` | Secret key as a hex string |
300
+ | `--b32` | Secret key as a base32 string |
301
+ | `-u, --uri` | Import from an `otpauth://` URI |
302
+ | `-g, --generate` | Generate a new random secret |
303
+ | `-i, --issuer` | Issuer name (e.g. "GitHub", "Google") |
304
+ | `--algo, --algorithm` | Hash algorithm (default: `sha512`) |
305
+ | `--digits` | Code length (default: 12) |
306
+ | `--period` | Time step in seconds (default: 45) |
307
+
308
+ ### `btotp list`
309
+
310
+ List all accounts in the vault with their current TOTP codes.
311
+
312
+ ```
313
+ btotp list
314
+ ```
315
+
316
+ ### `btotp show`
317
+
318
+ Show the current TOTP code for a specific account.
319
+
320
+ ```
321
+ btotp show NAME [--copy]
322
+ ```
323
+
324
+ | Flag | Description |
325
+ |---|---|
326
+ | `NAME` | Account name |
327
+ | `--copy` | Copy the code to clipboard |
328
+
329
+ ### `btotp remove`
330
+
331
+ Remove an account from the vault.
332
+
333
+ ```
334
+ btotp remove NAME
335
+ ```
336
+
337
+ ### `btotp rename`
338
+
339
+ Rename an account in the vault.
340
+
341
+ ```
342
+ btotp rename OLD_NAME NEW_NAME
343
+ ```
344
+
345
+ ### `btotp import-uri`
346
+
347
+ Import an account from an `otpauth://totp/...` URI.
348
+
349
+ ```
350
+ btotp import-uri URI [-n NAME]
351
+ ```
352
+
353
+ | Argument | Description |
354
+ |---|---|
355
+ | `URI` | The full `otpauth://totp/...` URI |
356
+ | `-n, --name` | Account name (defaults to the label from the URI) |
357
+
358
+ ### `btotp export`
359
+
360
+ Export the vault as plaintext JSON (secrets are visible — handle with care).
361
+
362
+ ```
363
+ btotp export [-o FILE]
364
+ ```
365
+
366
+ | Flag | Description |
367
+ |---|---|
368
+ | `-o, --output` | Write to file instead of stdout |
369
+
370
+ ### `btotp import`
371
+
372
+ Import accounts from a JSON file or stdin.
373
+
374
+ ```
375
+ btotp import [FILE]
376
+ ```
377
+
378
+ | Argument | Description |
379
+ |---|---|
380
+ | `FILE` | JSON file to import (reads from stdin if omitted) |
381
+
382
+ ### `btotp uri`
383
+
384
+ Generate an `otpauth://totp/...` URI for a vault account (for mobile enrollment).
385
+
386
+ ```
387
+ btotp uri NAME [--qr]
388
+ ```
389
+
390
+ | Flag | Description |
391
+ |---|---|
392
+ | `NAME` | Account name |
393
+ | `--qr` | Display the URI as a QR code in the terminal |
394
+
395
+ ### `btotp completion`
396
+
397
+ Generate shell completion script.
398
+
399
+ ```
400
+ btotp completion {bash,zsh,fish}
401
+ ```
402
+
403
+ **Usage:**
404
+
405
+ ```bash
406
+ # Bash
407
+ source <(btotp completion bash)
408
+
409
+ # Zsh
410
+ autoload -U bashcompinit && bashcompinit && source <(btotp completion zsh)
411
+
412
+ # Fish
413
+ btotp completion fish | source
414
+ ```
415
+
416
+ Requires `argcomplete` (`pip install bettertotp[completion]`).
417
+
418
+ ### `btotp config`
419
+
420
+ View or modify persistent configuration.
421
+
422
+ ```
423
+ btotp config [--show] [--set KEY=VALUE]
424
+ ```
425
+
426
+ | Flag | Description |
427
+ |---|---|
428
+ | `--show` | Display current configuration |
429
+ | `--set` | Set a configuration value |
430
+
431
+ **Available keys:**
432
+
433
+ | Key | Type | Default | Description |
434
+ |---|---|---|---|
435
+ | `time_step` | int | 45 | Default time step in seconds |
436
+ | `code_length` | int | 12 | Default code length in characters |
437
+ | `hash_algo` | string | `"sha512"` | Default hash algorithm |
438
+ | `clipboard` | bool | `false` | Always copy codes to clipboard |
439
+
440
+ Example:
441
+
442
+ ```bash
443
+ btotp config --set time_step=30
444
+ btotp config --set code_length=8
445
+ btotp config --show
446
+ ```
447
+
448
+ ### `btotp help`
449
+
450
+ Show help for any command.
451
+
452
+ ```
453
+ btotp help [COMMAND]
454
+ ```
455
+
456
+ Examples:
457
+
458
+ ```bash
459
+ btotp help
460
+ btotp help code
461
+ btotp help list
462
+ ```
463
+
464
+ ---
465
+
466
+ ## Python API
467
+
468
+ ### `generate_code(key_bytes, t=None, algorithm="sha512", code_length=12, time_step=45)`
469
+
470
+ Generate a TOTP code.
471
+
472
+ ```python
473
+ from btotp import generate_code
474
+
475
+ code = generate_code(b"your-secret-key")
476
+ code = generate_code(b"secret", algorithm="sha256", code_length=8, time_step=30)
477
+ ```
478
+
479
+ ### `verify_code(key_bytes, code, window=1, algorithm="sha512", code_length=12, time_step=45)`
480
+
481
+ Verify a TOTP code within a time window.
482
+
483
+ ```python
484
+ from btotp import verify_code
485
+
486
+ valid = verify_code(b"secret", code)
487
+ valid = verify_code(b"secret", code, algorithm="sha256", code_length=8)
488
+ ```
489
+
490
+ ### `generate_code_at(key_bytes, timestamp, ...)`
491
+
492
+ Generate a code for a specific Unix timestamp.
493
+
494
+ ```python
495
+ from btotp import generate_code_at
496
+
497
+ code = generate_code_at(b"secret", 1000000, time_step=30)
498
+ ```
499
+
500
+ ### `generate_secret(length=64)`
501
+
502
+ Generate a cryptographically random secret.
503
+
504
+ ```python
505
+ from btotp import generate_secret
506
+
507
+ secret = generate_secret() # 64 random bytes
508
+ secret = generate_secret(32) # 32 random bytes
509
+ ```
510
+
511
+ ### `Vault`
512
+
513
+ Encrypted vault for storing multiple secrets.
514
+
515
+ ```python
516
+ from btotp import Vault
517
+
518
+ vault = Vault()
519
+ vault.unlock("master-password")
520
+ vault.add("email", secret.hex(), issuer="Google")
521
+ code = vault.code("email")
522
+ accounts = vault.list_accounts()
523
+ vault.remove("email")
524
+ ```
525
+
526
+ **Methods:**
527
+
528
+ | Method | Description |
529
+ |---|---|
530
+ | `exists()` | Check if vault file exists |
531
+ | `create(password)` | Create a new vault |
532
+ | `unlock(password)` | Unlock an existing vault |
533
+ | `add(name, secret, ...)` | Add an account |
534
+ | `remove(name)` | Remove an account |
535
+ | `rename(old, new)` | Rename an account |
536
+ | `get(name)` | Get account details |
537
+ | `list_accounts()` | List all accounts |
538
+ | `code(name)` | Generate current code for account |
539
+ | `export_json()` | Export vault as JSON string |
540
+ | `import_json(data)` | Import accounts from JSON string |
541
+
542
+ ### `parse_otpauth(uri)`
543
+
544
+ Parse an `otpauth://totp/...` URI into its components.
545
+
546
+ ```python
547
+ from btotp import parse_otpauth
548
+
549
+ result = parse_otpauth("otpauth://totp/Example:user@example.com?secret=JBSWY3DPEHPK3PXP")
550
+ # {
551
+ # "secret": "...", # hex-encoded secret
552
+ # "issuer": "Example",
553
+ # "account": "user@example.com",
554
+ # "algorithm": "sha1",
555
+ # "digits": 12,
556
+ # "period": 45,
557
+ # }
558
+ ```
559
+
560
+ ### `generate_uri(account, secret_hex, issuer="", ...)`
561
+
562
+ Generate an `otpauth://totp/...` URI.
563
+
564
+ ```python
565
+ from btotp import generate_uri
566
+
567
+ uri = generate_uri("myaccount", secret.hex(), issuer="MyApp",
568
+ algorithm="sha256", digits=8, period=30)
569
+ ```
570
+
571
+ ---
572
+
573
+ ## Configuration
574
+
575
+ ### Vault file
576
+
577
+ Encrypted vault at `~/.config/btotp/vault.json`. The file contains:
578
+
579
+ ```json
580
+ {
581
+ "version": 1,
582
+ "salt": "<base64>",
583
+ "nonce": "<base64>",
584
+ "data": "<AES-256-GCM encrypted, base64-encoded JSON blob>"
585
+ }
586
+ ```
587
+
588
+ - **Encryption**: AES-256-GCM with random 12-byte nonce
589
+ - **Key derivation**: PBKDF2-HMAC-SHA256, 600,000 iterations, random 16-byte salt
590
+ - **Plaintext format** (when decrypted):
591
+
592
+ ```json
593
+ {
594
+ "accounts": {
595
+ "my-account": {
596
+ "secret": "a1b2c3d4...",
597
+ "issuer": "Example",
598
+ "algorithm": "sha512",
599
+ "digits": 12,
600
+ "period": 45
601
+ }
602
+ }
603
+ }
604
+ ```
605
+
606
+ ### User config
607
+
608
+ Persistent defaults at `~/.config/btotp/config.json`:
609
+
610
+ ```json
611
+ {
612
+ "time_step": 30,
613
+ "code_length": 8,
614
+ "hash_algo": "sha256",
615
+ "clipboard": true
616
+ }
617
+ ```
618
+
619
+ ---
620
+
621
+ ## Security Considerations
622
+
623
+ - The vault master password is the single point of failure. Choose a strong password.
624
+ - `btotp export` outputs **plaintext JSON** including all secrets. Handle exports securely.
625
+ - The vault file itself is encrypted with AES-256-GCM, but the encryption strength depends on your master password.
626
+ - PBKDF2 iterations are set to 600,000 (OWASP 2023 recommendation for SHA-256).
627
+ - Secret keys default to 64 bytes (512 bits) of random data via `secrets.token_bytes()`.
628
+
629
+ ---
630
+
631
+ ## Differences from Standard TOTP (RFC 6238)
632
+
633
+ | Aspect | Standard TOTP | BetterTOTP |
634
+ |---|---|---|
635
+ | Output | 6–8 decimal digits | 12 alphanumeric+special characters |
636
+ | Alphabet | `0-9` (10 chars) | `A-Z a-z 0-9 !@#$%&*-_+=?~` (75 chars) |
637
+ | Default hash | SHA-1 | SHA-512 |
638
+ | Default time step | 30 seconds | 45 seconds |
639
+ | Code generation | Dynamic truncation + modulo 10^N | Byte encoding into 75-char alphabet |
640
+ | Secret size | 10–20 bytes (80–160 bits) recommended | 64 bytes (512 bits) default |
641
+
642
+ ---
643
+
644
+ ## Changelog
645
+
646
+ ### v1.0.0
647
+
648
+ - **Android app** — Native Kotlin + Jetpack Compose APK in `android/`
649
+ - Dual vault modes: Master Password (PBKDF2 + AES-256-GCM) or Biometric (Android Keystore)
650
+ - TOTP core reimplemented in pure Kotlin (HMAC-SHA1/256/512, 75-char charset)
651
+ - Material 3 UI with dynamic color, navigation, and auto-refreshing codes
652
+ - **Linux binary** — PyInstaller-based standalone executable in `linux/`
653
+ - Tkinter GUI with unlock, live code list, add/copy/delete
654
+ - Automatic GUI/CLI fallback based on display availability
655
+ - `otpauth://` URI handler registration via xdg-mime
656
+ - **Web API** — FastAPI microservice for website backend integration in `web/`
657
+ - Stateless enrollment and verification endpoints (non-standard BetterTOTP algorithm)
658
+ - CORS configurable, ready for any web framework
659
+ - FOSS — MIT License. Author: Shri Kant
660
+
661
+ ### v0.2.0
662
+
663
+ - Configurable hash algorithm (`sha1`, `sha256`, `sha512`)
664
+ - Configurable code length and time step
665
+ - Encrypted vault (`btotp init`, `add`, `list`, `show`, `remove`, `rename`)
666
+ - `otpauth://totp/...` URI import (`btotp import-uri`)
667
+ - URI generation with optional QR display (`btotp uri --qr`)
668
+ - Clipboard copy support (`btotp code --copy`, `btotp show --copy`)
669
+ - User configuration (`btotp config`)
670
+ - Vault export/import (`btotp export`, `btotp import`)
671
+ - Shell completion scripts (`btotp completion`)
672
+ - `btotp help` subcommand
673
+
674
+ ### v0.1.0
675
+
676
+ - Initial release
677
+ - `btotp generate-secret`, `btotp code`, `btotp verify`
678
+ - HMAC-SHA512 with 12-char codes, 45-second time step
679
+ - Watch mode (`--watch`)
680
+
681
+ ---
682
+
683
+ ## License
684
+
685
+ MIT