Utilize age identity and recipient files - simplify some code - add a few ugly backwards-compat lifts - Rename "key.txt" to "identities" and move its location to the pa store dir - Move passwords into a dedicated "passwords" dir Co-authored-by: Alan Morgan <alanxoc3@gmail.com>
Jes Olson j3s@c3f.net
Tue, 27 Dec 2022 23:10:57 -0800
5 files changed,
53 insertions(+),
41 deletions(-)
M
contrib/pa-fuzzel
→
contrib/pa-fuzzel
@@ -2,7 +2,7 @@ #!/bin/sh
# # prompt for a password, then type the selected password -cd "${PA_DIR:-$HOME/.local/share/pa}" +cd "${PA_DIR:-$HOME/.local/share/pa/passwords}" password_files="$(find * -type f | grep -v '/.git')" password=$(printf '%s\n' "$password_files" | sed 's/.age//' | fuzzel -dmenu "$@")
M
contrib/pa-rofi
→
contrib/pa-rofi
@@ -1,6 +1,6 @@
#!/bin/sh -cd "${PA_DIR:-$HOME/.local/share/pa}" +cd "${PA_DIR:-$HOME/.local/share/pa/passwords}" password_files="$(find * -type f | grep -v '/.git')" password=$(printf '%s\n' "$password_files" | sed 's/.age//' | rofi -dmenu -i "$@")
M
pa
→
pa
@@ -1,6 +1,6 @@
#!/bin/sh # -# pa - simple age-based password manager +# pa - a simple password manager based on age pw_add() { name=$1@@ -43,7 +43,7 @@ #
# Heredocs are sometimes implemented via temporary files, # however this is typically done using 'mkstemp()' which # is more secure than a leak in '/proc'. - age -r "$pubkey" -o "$name.age" <<-EOF && + age -R "$recipients_file" -o "$name.age" <<-EOF && $pass EOF printf '%s\n' "Saved '$name' to the store."@@ -67,7 +67,7 @@ tmpdir="$(dirname "$tmpfile")"
mkdir -p "$tmpdir" trap 'rm -rf /dev/shm/pa' EXIT - age -i ~/.age/key.txt --decrypt "$name.age" 2>/dev/null >"$tmpfile" || + age -i "$identities_file" --decrypt "$name.age" 2>/dev/null >"$tmpfile" || die "Could not decrypt $name.age" "${EDITOR:-vi}" "$tmpfile"@@ -75,7 +75,7 @@
[ -f "$tmpfile" ] || die "New password not saved" rm "$name.age" - age -r "$pubkey" -o "$name.age" "$tmpfile" + age -R "$recipients_file" -o "$name.age" "$tmpfile" } pw_del() {@@ -90,7 +90,7 @@ }
} pw_show() { - age -i ~/.age/key.txt --decrypt "$1.age" 2>/dev/null || + age -i "$identities_file" --decrypt "$1.age" 2>/dev/null || die "Could not decrypt $1.age" }@@ -98,18 +98,9 @@ pw_list() {
find . -type f -name \*.age | sed 's/..//;s/\.age$//' } -pw_gen() { - if yn "$HOME/.age/key.txt not detected, generate a new one?"; then - mkdir -p ~/.age - age-keygen -o ~/.age/key.txt - fi -} - -depends() { - for dep in $@; do - command -v "$dep" >/dev/null 2>&1 || - die "$dep not found, install per https://github.com/FiloSottile/age" - done +dep() { + command -v "$1" >/dev/null 2>&1 || + die "$1 not found, install per https://github.com/FiloSottile/age" } yn() {@@ -167,15 +158,20 @@ }
usage() { printf %s "\ -pa 0.1.0 - age-based password manager -=> [a]dd [name] - Create a new password, randomly generated -=> [d]el [name] - Delete a password entry. -=> [e]dit [name] - Edit a password entry with $EDITOR. -=> [l]ist - List all entries. -=> [s]how [name] - Show password for an entry. -Password length: export PA_LENGTH=50 -Password pattern: export PA_PATTERN=_A-Z-a-z-0-9 -Store location: export PA_DIR=~/.local/share/pa + pa 0.1.1 + a simple password manager based on age + + commands: + [a]dd [name] - Create a new password, randomly generated + [d]el [name] - Delete a password entry. + [e]dit [name] - Edit a password entry with $EDITOR. + [l]ist - List all entries. + [s]how [name] - Show password for an entry. + + default env vars: + Password length: export PA_LENGTH=50 + Password pattern: export PA_PATTERN=_A-Z-a-z-0-9 + Password/key dir: export PA_DIR=~/.local/share/pa " exit 0 }@@ -183,13 +179,22 @@
main() { : "${PA_DIR:=${XDG_DATA_HOME:=$HOME/.local/share}/pa}" - depends age age-keygen + password_dir="$PA_DIR/passwords" - mkdir -p "$PA_DIR" || - die "Couldn't create password directory" + mkdir -p "$password_dir" || + die "Couldn't create password store" - cd "$PA_DIR" || - die "Can't access password directory" + cd "$password_dir" || + die "Can't access the password store" + + # Move any passwords hanging out in the old dir + # for backwards-compat reasons + set +f + mv ~/.local/share/pa/*.age "$password_dir" 2>/dev/null + set -f + + glob "$1" '[aes]' && + depends age glob "$1" '[ades]*' && [ -z "$2" ] && die "Missing [name] argument"@@ -213,8 +218,18 @@ # Restrict permissions of any new files to
# only the current user. umask 077 - [ -f ~/.age/key.txt ] || pw_gen - pubkey=$(sed -n 's/.*\(age\)/\1/p' ~/.age/key.txt) + identities_file="$PA_DIR/identities" + # Copy any existing identities files from the old + # storage location to the new one - backwards compat. + [ ! -f "$identities_file" ] && [ -f ~/.age/key.txt ] && + cp ~/.age/key.txt "$identities_file" + + [ ! -f "$identities_file" ] && dep age-keygen && + age-keygen -o "$identities_file" 2>/dev/null + + recipients_file="$PA_DIR/recipients" + [ ! -f "$recipients_file" ] && dep age-keygen && + age-keygen -y -o "$recipients_file" "$identities_file" 2>/dev/null # Ensure that we leave the terminal in a usable # state on exit or Ctrl+C.@@ -233,9 +248,6 @@
# Ensure that debug mode is never enabled to # prevent the password from leaking. set +x - -# -set -e # Ensure that globbing is globally disabled # to avoid insecurities with word-splitting.