From 611157c86db0e1e3e97191271ad2b17c073a22ff Mon Sep 17 00:00:00 2001 From: drduh Date: Sun, 30 Jun 2024 14:39:57 -0700 Subject: [PATCH 1/3] Generate username and clipboard features from pwd.sh --- purse.sh | 102 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 56 insertions(+), 46 deletions(-) diff --git a/purse.sh b/purse.sh index 205c47e..e5749a8 100755 --- a/purse.sh +++ b/purse.sh @@ -9,10 +9,11 @@ export LC_ALL="C" now="$(date +%s)" today="$(date +%F)" -copy="$(command -v xclip || command -v pbcopy)" gpg="$(command -v gpg || command -v gpg2)" -gpg_conf="${GNUPGHOME}/gpg.conf" +gpg_conf="${HOME}/.gnupg/gpg.conf" +copy="${PWDSH_CLIP:=xclip}" # clipboard, 'pbcopy' on macOS +copy_args=${PWDSH_COPY_ARGS:=} # args to pass to copy command clip_dest="${PURSE_DEST:=clipboard}" # set to 'screen' to print to stdout clip_timeout="${PURSE_TIME:=10}" # seconds to clear clipboard/screen comment="${PURSE_COMMENT:=}" # *unencrypted* comment in files @@ -31,8 +32,7 @@ cleanup () { # "Lock" files on trapped exits. ret=$? - chmod -R 0000 \ - "${safe_dir}" "${safe_ix}" 2>/dev/null + chmod -R 0000 "${safe_dir}" "${safe_ix}" 2>/dev/null exit ${ret} } @@ -49,9 +49,33 @@ warn () { tput setaf 3 ; printf "\nWARNING: %s\n" "${1}" ; tput sgr0 } +setup_keygroup() { + # Configure one or more recipients. + + purse_keygroup="group purse_keygroup =" + keyid="" + recommend="$(${gpg} -K | grep "sec#" | \ + awk -F "/" '{print $2}' | cut -c-18 | tr "\n" " ")" + + printf "\n Setting up keygroup ...\n + Found recommended key IDs: %s\n + Enter one or more key IDs, preferred one last\n" "${recommend}" + + while [[ -z "${keyid}" ]] ; do read -r -p " + Key ID or Enter to continue: " keyid + if [[ -z "${keyid}" ]] ; then + printf "%s\n" "${purse_keygroup}" >> "${gpg_conf}" + break + fi + purse_keygroup="${purse_keygroup} ${keyid}" + keyid="" + done +} + get_pass () { # Prompt for a password. + password="" prompt=" ${1}" printf "\n" @@ -105,20 +129,19 @@ read_pass () { tail -1 | cut -d ":" -f2) fi + if [[ ! -s "${spath}" ]] ; then + fail "Secret not available" ; fi + prompt_key "password" - if [[ -s "${spath}" ]] ; then - clip <(decrypt "${spath}" | head -1) || \ - fail "Failed to decrypt ${spath}" - else fail "Secret not available" - fi + clip <(decrypt "${spath}" | head -1) || \ + fail "Failed to decrypt ${spath}" } prompt_key () { # Print a message if safe file exists. if [[ -f "${safe_ix}" ]] ; then - printf "\n Touch key to access %s ...\n" "${1}" - fi + printf "\n Touch key to access %s ...\n" "${1}" ; fi } gen_pass () { @@ -129,13 +152,22 @@ gen_pass () { else length="${3}" ; fi if [[ "${length}" =~ ^[0-9]+$ ]] ; then - pass_len="${length}" - fi + pass_len="${length}" ; fi tr -dc "${pass_chars}" < /dev/urandom | \ fold -w "${pass_len}" | head -1 } +gen_user () { + # Generate a username. + + printf "%s%s\n" \ + "$(awk 'length > 2 && length < 12 {print(tolower($0))}' \ + /usr/share/dict/words | grep -v "'" | sort -R | head -n2 | \ + tr "\n" "_" | iconv -f utf-8 -t ascii//TRANSLIT)" \ + "$(tr -dc "[:digit:]" < /dev/urandom | fold -w 4 | head -1)" +} + write_pass () { # Write a password and update the index. @@ -143,11 +175,9 @@ write_pass () { fold -w10 | head -1)" if [[ -n "${pass_copy}" ]] ; then - clip <(printf '%s' "${userpass}") - fi + clip <(printf '%s' "${userpass}") ; fi - printf '%s\n' "${userpass}" | \ - encrypt "${spath}" - || \ + printf '%s\n' "${userpass}" | encrypt "${spath}" - || \ fail "Failed saving ${spath}" if [[ -n "${encrypt_index}" ]] ; then @@ -208,37 +238,15 @@ clip () { else printf "\n" ; printf "" | "${copy}" ; fi } -setup_keygroup() { - # Configure one or more recipients. - - purse_keygroup="group purse_keygroup =" - keyid="" - recommend="$(${gpg} -K | grep "sec#" | \ - awk -F "/" '{print $2}' | cut -c-18 | tr "\n" " ")" - - printf "\n Setting up keygroup ...\n - Found recommended key IDs: %s\n - Enter one or more key IDs, preferred one last\n" "${recommend}" - - while [[ -z "${keyid}" ]] ; do read -r -p " - Key ID or Enter to continue: " keyid - if [[ -z "${keyid}" ]] ; then - printf "%s\n" "${purse_keygroup}" >> "${gpg_conf}" - break - fi - purse_keygroup="${purse_keygroup} ${keyid}" - keyid="" - done -} - new_entry () { # Prompt for username and password. - while [[ -z "${username}" ]] ; do - if [[ -z "${2+x}" ]] ; then read -r -p " - Username: " username - else username="${2}" ; fi - done + if [[ -z "${2+x}" ]] ; then read -r -p " + Username (Enter to generate): " username + else username="${2}" ; fi + if [[ -z "${username}" ]] ; then + username=$(gen_user "$@") + fi if [[ -z "${3+x}" ]] ; then get_pass "Password for \"${username}\" (Enter to generate): " @@ -283,9 +291,11 @@ if [[ ! -d "${safe_dir}" ]] ; then mkdir -p "${safe_dir}" ; fi chmod -R 0700 "${safe_dir}" "${safe_ix}" 2>/dev/null -if [[ -z "${copy}" || ! -x "${copy}" ]] ; then +if [[ -z "$(command -v ${copy})" ]] ; then warn "Clipboard not available, passwords will print to screen/stdout!" clip_dest="screen" +elif [[ -n "${copy_args}" ]] ; then + copy+=" ${copy_args}" fi username="" From f8d7bb794ac67e779c29f9d2721f030cc46a2902 Mon Sep 17 00:00:00 2001 From: drduh Date: Sun, 30 Jun 2024 16:16:26 -0700 Subject: [PATCH 2/3] Better variable names, fix xclip selection --- README.md | 2 ++ purse.sh | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 0499a36..0d78046 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,8 @@ Several customizable options and features are also available, and can be configu Variable | Description | Default | Values -|-|-|- +`PURSE_CLIP` | clipboard to use | `xclip` | `pbcopy` on macOS +`PURSE_CLIP_ARGS` | arguments to pass to clipboard command | unset (disabled) | `-i -selection clipboard` to use primary (control-v) clipboard with xclip `PURSE_TIME` | seconds to clear password from clipboard/screen | `10` | any valid integer `PURSE_LEN` | default generated password length | `14` | any valid integer `PURSE_COPY` | copy password to clipboard before write | unset (disabled) | `1` or `true` to enable diff --git a/purse.sh b/purse.sh index e5749a8..860a484 100755 --- a/purse.sh +++ b/purse.sh @@ -10,10 +10,10 @@ export LC_ALL="C" now="$(date +%s)" today="$(date +%F)" gpg="$(command -v gpg || command -v gpg2)" -gpg_conf="${HOME}/.gnupg/gpg.conf" +gpg_conf="${GNUPGHOME}/gpg.conf" -copy="${PWDSH_CLIP:=xclip}" # clipboard, 'pbcopy' on macOS -copy_args=${PWDSH_COPY_ARGS:=} # args to pass to copy command +clip="${PWDSH_CLIP:=xclip}" # clipboard, 'pbcopy' on macOS +clip_args=${PWDSH_CLIP_ARGS:=} # args to pass to copy command clip_dest="${PURSE_DEST:=clipboard}" # set to 'screen' to print to stdout clip_timeout="${PURSE_TIME:=10}" # seconds to clear clipboard/screen comment="${PURSE_COMMENT:=}" # *unencrypted* comment in files @@ -144,7 +144,7 @@ prompt_key () { printf "\n Touch key to access %s ...\n" "${1}" ; fi } -gen_pass () { +generate_pass () { # Generate a password from urandom. if [[ -z "${3+x}" ]] ; then read -r -p " @@ -158,7 +158,7 @@ gen_pass () { fold -w "${pass_len}" | head -1 } -gen_user () { +generate_user () { # Generate a username. printf "%s%s\n" \ @@ -225,7 +225,7 @@ clip () { if [[ "${clip_dest}" = "screen" ]] ; then printf '\n%s\n' "$(cat ${1})" - else "${copy}" < "${1}" ; fi + else ${clip} < "${1}" ; fi printf "\n" while [[ "${clip_timeout}" -gt 0 ]] ; do @@ -235,7 +235,7 @@ clip () { printf "\r\033[K Clearing password from %s ..." "${clip_dest}" if [[ "${clip_dest}" = "screen" ]] ; then clear - else printf "\n" ; printf "" | "${copy}" ; fi + else printf "\n" ; printf "" | ${clip} ; fi } new_entry () { @@ -245,7 +245,7 @@ new_entry () { Username (Enter to generate): " username else username="${2}" ; fi if [[ -z "${username}" ]] ; then - username=$(gen_user "$@") + username=$(generate_user "$@") fi if [[ -z "${3+x}" ]] ; then @@ -255,7 +255,7 @@ new_entry () { printf "\n" if [[ -z "${password}" ]] ; then - userpass=$(gen_pass "$@") + userpass=$(generate_pass "$@") fi } @@ -291,11 +291,11 @@ if [[ ! -d "${safe_dir}" ]] ; then mkdir -p "${safe_dir}" ; fi chmod -R 0700 "${safe_dir}" "${safe_ix}" 2>/dev/null -if [[ -z "$(command -v ${copy})" ]] ; then +if [[ -z "$(command -v ${clip})" ]] ; then warn "Clipboard not available, passwords will print to screen/stdout!" clip_dest="screen" -elif [[ -n "${copy_args}" ]] ; then - copy+=" ${copy_args}" +elif [[ -n "${clip_args}" ]] ; then + clip+=" ${clip_args}" fi username="" From ab5a41790dc630bf97dedcfa4e417282fbec5ec0 Mon Sep 17 00:00:00 2001 From: drduh Date: Thu, 4 Jul 2024 15:06:17 -0700 Subject: [PATCH 3/3] Improve gpg.conf path --- purse.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/purse.sh b/purse.sh index 860a484..0a236a7 100755 --- a/purse.sh +++ b/purse.sh @@ -10,7 +10,7 @@ export LC_ALL="C" now="$(date +%s)" today="$(date +%F)" gpg="$(command -v gpg || command -v gpg2)" -gpg_conf="${GNUPGHOME}/gpg.conf" +gpg_conf="${HOME}/.gnupg/gpg.conf" clip="${PWDSH_CLIP:=xclip}" # clipboard, 'pbcopy' on macOS clip_args=${PWDSH_CLIP_ARGS:=} # args to pass to copy command