{"id":19924308,"url":"https://github.com/apptension/onetimepass","last_synced_at":"2025-08-24T14:38:30.943Z","repository":{"id":42174342,"uuid":"434866662","full_name":"apptension/onetimepass","owner":"apptension","description":"CLI client for RFC 4226's HOTP and RFC 6238's TOTP.","archived":false,"fork":false,"pushed_at":"2025-05-26T18:45:53.000Z","size":2194,"stargazers_count":13,"open_issues_count":9,"forks_count":1,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-06-29T04:03:32.333Z","etag":null,"topics":["cli","hotp","otpauth","python","totp"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/apptension.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-12-04T10:08:37.000Z","updated_at":"2025-05-22T19:35:38.000Z","dependencies_parsed_at":"2025-06-05T07:37:50.678Z","dependency_job_id":"6d22c092-394f-439b-8c2c-7c97aa1a1c6a","html_url":"https://github.com/apptension/onetimepass","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/apptension/onetimepass","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apptension%2Fonetimepass","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apptension%2Fonetimepass/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apptension%2Fonetimepass/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apptension%2Fonetimepass/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/apptension","download_url":"https://codeload.github.com/apptension/onetimepass/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apptension%2Fonetimepass/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271888274,"owners_count":24839141,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-24T02:00:11.135Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","hotp","otpauth","python","totp"],"created_at":"2024-11-12T22:17:00.832Z","updated_at":"2025-08-24T14:38:30.903Z","avatar_url":"https://github.com/apptension.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# One Time Password (OTP, TOTP/HOTP)\n\n[![Python 3.10](https://img.shields.io/badge/python-3.10-green.svg)](https://www.python.org/downloads/release/python-3100/)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n[![pdm-managed](https://img.shields.io/badge/pdm-managed-blueviolet)](https://pdm.fming.dev)\n[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit\u0026logoColor=white)](https://github.com/pre-commit/pre-commit)\n\n---\nOTP serves as additional protection in case of password leaks.\n\n`onetimepass` allows you to manage OTP codes and generate a master key.\nThe master key allows the base to be decrypted and encrypted. Make sure to keep it in a safe place, otherwise it will\nnot be possible to recover the data.\n\n`onetimepass` supports as an optional dependency the integration with the system keychain (cross-platform) in which the\napplication saves the master key.\n\n## Requirements\n\n- Python 3.10+\n- PDM 1.11+\n\n## Installation\n\n```console\n$ pdm install\n```\n\nTo include the optional keychain support:\n```console\n$ pdm install -G keyring\n```\n\n## Usage\n\n![](docs/usage.png)\n\n### Initialize database\n\nAt the very beginning, the database must be initialised, which additionally creates the master key.\nIt will save it to the keychain if this has been installed.\n\nBy default, it will print the generated key to the STDOUT. You need this behavior if you don't use the optional keychain\nintegration.\n\nIf you do, you can pass the `-q, --quiet` option to silence the output.\n\n![](docs/master-key-init.png)\n\n### Keychain integration\n\nThe application will automatically detect if you have the keychain integration installed, however, if you want to force\nenable/disable it, you can by using respectively the `-k, --keyring` and `-K, --no-keyring` options.\n\nAlthough, if you don't have the keychain integration installed, enabling it won't work:\n![](docs/keyring-not-installed.png)\n\n\n### Print the master key\n\nIt is possible to print the current master key stored in the keychain (if you need this for e.g. migrating the app to\nthe different device).\n\nThis of course won't work if you don't use the keychain integration.\n\n![](docs/master-key-show.png)\n\n### Adding new OTP alias\n\n`onetimepass` identifies the added OTP codes via the user-specified _aliases_, which should be short, easy-to-remember\nnames.\n\n`onetimepass` allows you to add new alias in two ways, either by specifying all the parameters manually,\nusing `add hotp` or `add totp` commands (depending on which type of the OTP you want to add), or by providing\nthe [de facto standard URI](https://github.com/google/google-authenticator/wiki/Key-Uri-Format) invented by the Google.\n\n#### Adding via URI (command will aks interactively for the URI)\n```console\n$ pdm run otp add uri AWS-root\nEnter URI:\nRepeat for confirmation:\n```\n\nExample URIs\n\n* TOTP: [otpauth://totp/ACME%20Co:john@example.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ\u0026issuer=ACME%20Co\u0026algorithm=SHA1\u0026digits=6\u0026period=30]()\n* HOTP: [otpauth://totp/ACME%20Co:john@example.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ\u0026issuer=ACME%20Co\u0026algorithm=SHA1\u0026digits=6\u0026period=30]()\n\n#### Adding via totp/hotp subcommand (command will ask interactively for the secret):\n```console\n$ pdm run otp add totp AWS-root\nEnter secret:\nRepeat for confirmation:\n$ pdm run otp add hotp AWS-root\nEnter secret:\nRepeat for confirmation:\n```\n\n### Removing OTP alias\n\n```console\n$ pdm run otp rm \u003calias\u003e\nAre you sure? [y/N]:\n```\n\nTo omit the interactive confirmation (⚠️ **unsafe!**), pas the `--yes` option.\n\n### Showing OTP code\n\n```console\n$ pdm run otp show \u003calias\u003e\n```\n\n![](docs/show-alias.png)\n\nYou can force the app to wait until the new OTP code is valid, in case the current one will be invalid in a short period\nof time (so you won't have to rush with copy-pasting the code, or wait manually), using `-w, --wait-for-next` option.\n\n```console\n$ pdm run otp show -w \u003cseconds\u003e \u003calias\u003e\n```\n\nThis will accept the _seconds_ of tolerance (if the remaining time of the current code to be valid is less than\n_seconds_, the app will wait, otherwise it will show the current code).\n\n![](docs/wait-for-next-otp.gif)\n\nYou can easily automate it even more:\n\n```console\n$ pdm run otp show -w 10 \u003calias\u003e | cut -d' ' -f2 | pbcopy; alert\n```\n\nTo extract the code when it's ready, then copy it to the system clipboard (`pbcopy` for macOS, `xclip` for Linux), and\nsend the system notification to yourself when it's all finished (assuming you have the `alert` alias configured,\navailable by default e.g. on Ubuntu Linux).\n\n### Database import/export\n\nIn case you want to migrate the application to the different device, you can export the local database to the format of\nchoice (currently only the `json` is supported) and then import it.\n\n![](docs/database-import.png)\n\n![](docs/database-import-conflict.png)\n\nYou can use this not only to transfer the application between the devices, but also to create backups:\nbecause `onetimepass` is a CLI-based tool, you can even implement the cronjob that will periodically run the `export` in\nthe background (⚠️ just remember to encrypt the resulting file and store it somewhere safe).\n\n### Shell Completion\n\n`onetimepass` can provide tab completion for commands, options, and choice values. Bash, Zsh, and Fish are supported\n\n```console\n$ pdm run zsh\n$ eval \"$(_OTP_COMPLETE=zsh_source otp)\"\n```\n\n```console\n$ pdm run bash\n$ eval \"$(_OTP_COMPLETE=bash_source otp)\"\n```\n\n![](docs/otp-shell-completion.png)\n\n## Rationale\n\nAs the `onetimepass` have multiple alternatives, you may ask why bother with reinventing the wheel instead of using any\nexisting solution.  \nThis section addresses that.\n\n### Existing alternatives\n\n#### [Google Authenticator](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2)\n\nThe main issue with this app is that it does not offer any way to backup the secrets, and synchronize them between the\ndevices.\n\nIf you don't have the backup of the original QR codes, and you'll lose your mobile phone, you're screwed. Yes, services\nthat provide the 2FA often offer the backup codes, but not every one of them, and this is not the optimal solution.\n\nIn theory, if you root the device, you can access the local database, but not everyone wants or can root their mobile\nphone, as this can e.g. void a device's warranty.\n\nBesides, if you root the device, you can see the local database is stored in the plain text, which is a big security\nrisk.\n\n#### [Authy](https://authy.com/)\n\nIt does allow synchronizing secrets between the devices, but this happens through the provider servers. The\napplication [neither sent nor store your backup password](https://support.authy.com/hc/en-us/articles/115001750008-Backups-and-Sync-in-Authy), but\nit can still be non-optimal for some people to trust the external provider to handle such sensitive data.\n\nAlso, Authy\n[does not support export or import](https://support.authy.com/hc/en-us/articles/1260805179070-Export-or-Import-Tokens-in-the-Authy-app)\nof the secrets.\n\n#### [pass](https://www.passwordstore.org/) or [gopass](https://www.gopass.pw/)\n\n`pass` is an extensible CLI-based password manager, and there is a [pass-otp](https://github.com/tadfisher/pass-otp)\nplugin to handle TOTP (although, HOTP is not supported).\n\nOne issue is that it uses GnuPG for encrypting the local database, which can be tedious to configure:\n\u003e To be honest, a few first times I tried to configure it, I failed miserably. This should be much easier and faster.\n~ [Daniel Staśczak](https://github.com/Toreno96)\n\nThe second issue is that, as mentioned above, `pass` is _primarily_ the password manager.\nIf one wants only the TOTP client, it's a little bit of an overkill to install the whole password manager for that.\n\n### The GUI clients in general\n\nThis is more of a personal preference, but if you use the GUI-based OTP client, especially on your mobile phone, there\nare some extra steps everytime you need to use it:\n1. You have to get your phone.\n2. You have to open the app.\n3. You have to type the code manually, if you need to enter the code on another device (e.g. to authorize on the\n   desktop).\n\nThis is _not_ very inconvenient, but I bet there were at least few times when you didn't had your phone with you while\nyou had to authorize into the AWS account while working on something urgent, or get your phone out of the pocket every\nfew hours, because the Keeper logged out you out of a sudden once again in a day.\n\nIf you're CLI power-user, using the CLI-based tool is just much quicker and convenient. And you can create some crazy\npipelines (see the examples in the **Usage** section).\n\n### Security\n\nWhile `onetimepass` does reinvent a wheel in general, one of the main goals of the project is to still be a secure\nsolution, and do _not_ reinvent the wheel in regard to the security. Because of this reason, for generating the master\nkey and encrypting the local database, the [high-level cryptographic library](https://cryptography.io/en/latest/) is\nused.\n\nThe main algorithm for the HOTP/TOTP is implemented based on the official RFC and the reference implementation.\n\nThere are some functionalities which can be a security hole if used in an irresponsible manner (e.g. `export`, `key`),\nbut the same can be said about the `sudo rm -rf --np-preserve-root /`, right?\n\nNevertheless, if you see any security issue, please feel free to report it, we're more than happy to consider it.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapptension%2Fonetimepass","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapptension%2Fonetimepass","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapptension%2Fonetimepass/lists"}