Skip to content

Commit

Permalink
chore: Update mytotp script to provide help, format readme file for m…
Browse files Browse the repository at this point in the history
…ytotp.rc
  • Loading branch information
uyriq committed May 10, 2024
1 parent 57e0d4a commit 33cf200
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 25 deletions.
66 changes: 41 additions & 25 deletions mytotp.rc
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
#!/bin/bash
# this code is a fork of https://github.com/ThingCrimson/mytotp
# there are prerequisites to use this code:
# 1. gpg
# 2. oathtool
# 3. xclip (optional, for Linux only) or pbpaste (it is included in MacOS)
# 4. that for MacOS only bash 5.2.26, if you have older version that is default case for MacOS, please upgrade it with brew or use previous version of script,
# see this repo releases for MacOS standard bash
# put this file in ~ path and source it in .bashrc or .zshrc
# if [ -f $HOME/mytotp.rc ]; then
# . $HOME/mytotp.rc
Expand All @@ -15,41 +22,49 @@
# mytotpadd SERVID
# usage, listing all SERVIDs:
# mytotplist

KEYDIR=~/.config/mytotp
KEYEXT=.gpg
if [ "$(uname)" == "Darwin" ]; then
PASTECOMMAND="pbpaste"
# make check of bash version, if it is even to 3.2.57 then show warning and instructions how to upgrade shell to bash 5.2.26 with brew, then exit with code 1
if [ "$(echo $BASH_VERSION | awk -F. '{print $1}')" -eq 3 ] && [ "$(echo $BASH_VERSION | awk -F. '{print $2}')" -eq 2 ] && [ "$(echo $BASH_VERSION | awk -F. '{print $3}')" -eq 57 ]; then
echo "Your MacOS bash version is too old, please upgrade it to 5.2.26 with brew, following these steps"
echo "brew install bash"
echo "sudo ln -s /opt/homebrew/bin/bash /usr/local/bin/bash "
echo "sudo bash -c 'echo /usr/local/bin/bash >> /etc/shells'"
echo "optional step to change default zsh to bash, not really needed: chsh -s /usr/local/bin/bash"
return 1
fi
fi
if [ "$(uname)" == "Linux" ]; then
if ! command -v xclip &>/dev/null; then
echo "xclip could not be found. It is an optional tool for reading the initial key from the clipboard."
echo "If you want to use this optional feature, please install it with: sudo apt-get install xclip"
read -p "Do you want to continue without xclip? (y/n) " yn
case $yn in
[Yy]*) ;;
[Nn]*) return 1 ;;
*) echo "Please answer yes or no." ;;
esac
fi
PASTECOMMAND="xclip -o"
fi

function mytotp() {
SERVID=$1

if ! command -v oathtool &>/dev/null; then
echo "oathtool could not be found"
echo "Please install it with: brew install oath-toolkit"
echo "or check further https://launchpad.net/oath-toolkit/+packages && https://www.nongnu.org/oath-toolkit/"
return 1
fi

if [ "$(uname)" == "Darwin" ]; then
PASTECOMMAND="pbpaste"
fi

if [ "$(uname)" == "Linux" ]; then
if ! command -v xclip &>/dev/null; then
echo "xclip could not be found. It is an optional tool for reading the initial key from the clipboard."
echo "If you want to use this optional feature, please install it with: sudo apt-get install xclip"
read -p "Do you want to continue without xclip? (y/n) " yn
case $yn in
[Yy]*) ;;
[Nn]*) return 1 ;;
*) echo "Please answer yes or no." ;;
esac
fi
PASTECOMMAND="xclip -o"
fi

if [ -z "${SERVID}" ]; then
echo -e "Usage: $0 SERVID\n\tSERVID is a service ID, abbreviated, w/o ext:"
find ${KEYDIR}/*${KEYEXT} | sed -e 's/\/home.*\// /; s/\.gpg//'
return 2
if [ -z "$1" ]; then
echo "mytotp version 1.0.0.rc"
echo "Usage: mytotp SERVID"
echo "SERVID is a service ID, abbreviated, that you provided for mytotpadd before, check all with mytotplist command"
return 1
fi

if [ ! -f "${KEYDIR}/${SERVID}${KEYEXT}" ]; then
Expand Down Expand Up @@ -105,9 +120,10 @@ function mytotpadd() {
echo "Paste the key in the prompt, press enter, and then press control-D to stop gpg"
gpg -e -r "My TOTP" >~/.config/mytotp/$SERVID.gpg
# if you want paste again the key, this way it would be stored in ~/.config/mytotp/SERVIDS.keys.lst file
read -p "Do you want to store the initial service key in ~/.config/mytotp/${SERVID}.key.asc? warn: it is unsafe (y/n)" yn
case $yn in
# read from clipboard with xclip
echo "Do you want to store the initial service key in .key.asc? Warn: it is unsafe (y/n) "
read -p "y/n " byn
case $byn in
[Yy]*) $PASTECOMMAND >>~/.config/mytotp/${SERVID}.key.asc ;;
[Nn]*) return ;;
*) echo "Please answer yes or no." ;;
Expand Down
50 changes: 50 additions & 0 deletions mytotp.rc.README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# mytotp.rc

TOTP 2FA without smartphone

Simple replacement of TOTP Authenticator mobile app for POSIX console (using `oathtool`).

Now in two versions: plain BASH script and BASH functions for sourcing.

This readme file is about `mytotp.rc` version, if you want `mytotp.sh` then skip to [main README.md](./README.md)

## Prerequisits

POSIX-compliant console, with BASH, GNU utils, GNU Privacy Guard and `oathtool` available. The latest script version require MacOS bash be upgraded to modern version. see bellow for details. If you dont want to upgrade standard MacOS bash, then use previos ugly script version from [releases here](https://github.com/uyriq/mytotp_as_bashfuncs/releases/tag/0.0.1.rc)
for latest scipt then we need xclip (optional, for Linux only) or pbpaste (it is included in MacOS by default)
Note, that installed `brew` is required for MacOS, if you want to install modern bash. after `brew install bash` make symlink `sudo ln -s /opt/homebrew/bin/bash /usr/local/bin/bash` then you do not need to `chsh` your shell from zsh to bash, it is more convinient to use subshell with call of `/usr/local/bin/bash` and keep zsh as default

## Instalation

Put this file in ~ path and source it in .bashrc or .zshrc
like this

```bash
if [ -f $HOME/mytotp.rc ]; then
. $HOME/mytotp.rc
fi
```

or just add next line to .bashrc or .zshrc
`source /path/to/somewhere/isplaced/mytotp.rc`

MacOS users with default zsh should start modern bash calling `/usr/local/bin/bash` then do `source /path/to/somewhere/isplaced/mytotp.rc`

Create a direcrory for TOTP keys `mkdir -p ~/.config/mytotp` it can be done with `mytotplist` command as well

If you have no suitable GPG key for encrypting of TOTP keys, create it
`gpg --yes --batch --passphrase-fd 0 --quick-generate-key 'My TOTP'`
enter your passphrase, (rememeber it) hit Enter, check keys with
`gpg --list-secret-keys | grep "My TOTP" ` you should view `[ultimate] My TOTP`

## Usage

To use these commands, follow these steps:

1. **List Services with `mytotplist`**: This command lists all the services that have been added to the TOTP generator. It reads the GPG files in the `~/.config/mytotp/` directory and prints the service IDs. If the `~/.config/mytotp` directory does not exist, the function will prompt the user to create it.

2. **Add a Service with `mytotpadd SERVID`**: When you activate 2FA on a service (let's call it SERVID), you will receive a TOTP key string. Copy this string, then run `mytotpadd SERVID`. This command adds a new service to the TOTP generator. You will be prompted to enter the service's initial secret key. This key is usually displayed as a QR code, but we need the alphanumeric form of this initial secret code. The service and its secret key will be stored in a GPG file in the `~/.config/mytotp/` directory. Optionally, the initial secret can be stored in a plain text file in the same directory. However, this is a development option and is not recommended for daily use due to security concerns. After running `mytotpadd SERVID`, paste the initial code string, then press <kbd>Enter</kbd> and <kbd>Ctrl</kbd>+<kbd>D</kbd>.

3. **Generate a TOTP with `mytotp SERVID`**: This command generates a Time-based One-Time Password (TOTP) for the specified service ID (SERVID). The output is a standard 6-digit TOTP code, which may not be compatible with other TOTP formats (e.g., Yandex TOTP). If no service ID is provided, the command will print usage help and version information. The `mytotp` function is identical to the standalone `mytotp.sh` script. For more information, see the [main README.md](./README.md).

To get a TOTP code for a service, run `mytotp.sh SERVID`, unlock your GPG key with the passphrase, then wait for the 6-digit code. The script will wait for the next 30-second interval before generating the code, giving you a maximum of 30 seconds to use it.

0 comments on commit 33cf200

Please sign in to comment.