password-store

Simple password manager using gpg and ordinary unix directories
git clone https://git.zx2c4.com/password-store
Log | Files | Refs | README | LICENSE

commit ff62f87f41557ab7267defab662324927301485a
parent 2bc437df229865456a77fbb982e187aa69304e98
Author: Jason A. Donenfeld <Jason@zx2c4.com>
Date:   Mon, 19 Dec 2016 03:44:03 +0100

Add signatures

Diffstat:
Mman/pass.1 | 7+++++++
Msrc/password-store.sh | 24++++++++++++++++++++++++
2 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/man/pass.1 b/man/pass.1 @@ -445,6 +445,13 @@ for more info. The location to look for executable extension files, by default \fIPASSWORD_STORE_DIR/.extensions\fP. .TP +.I PASSWORD_STORE_SIGNING_KEY +If this environment variable is set, then all \fB.gpg-id\fP files and extension files +must be signed using a detached signature using the GPG key specified by the full 40 character +upper-case fingerprint in this variable. If multiple fingerprints are specified, each +separated by a whitespace character, then signatures must match at least one. +The \fBinit\fP command will keep signatures of \fB.gpg-id\fP files up to date. +.TP .I EDITOR The location of the text editor used by \fBedit\fP. .SH SEE ALSO diff --git a/src/password-store.sh b/src/password-store.sh @@ -49,6 +49,17 @@ die() { echo "$@" >&2 exit 1 } +verify_file() { + [[ -n $PASSWORD_STORE_SIGNING_KEY ]] || return 0 + [[ -f $1.sig ]] || die "Signature for $1 does not exist." + local fingerprints="$(gpg $PASSWORD_STORE_GPG_OPTS --verify --status-fd=1 "$1.sig" "$1" 2>/dev/null | sed -n 's/\[GNUPG:\] VALIDSIG \([A-F0-9]\{40\}\) .* \([A-F0-9]\{40\}\)$/\1\n\2/p')" + local fingerprint found=0 + for fingerprint in $PASSWORD_STORE_SIGNING_KEY; do + [[ $fingerprint =~ ^[A-F0-9]{40}$ ]] || continue + [[ $fingerprints == *$fingerprint* ]] && { found=1; break; } + done + [[ $found -eq 1 ]] || die "Signature for $1 is invalid." +} set_gpg_recipients() { GPG_RECIPIENT_ARGS=( ) GPG_RECIPIENTS=( ) @@ -78,6 +89,8 @@ set_gpg_recipients() { exit 1 fi + verify_file "$current" + local gpg_id while read -r gpg_id; do GPG_RECIPIENT_ARGS+=( "-r" "$gpg_id" ) @@ -291,6 +304,16 @@ cmd_init() { local id_print="$(printf "%s, " "$@")" echo "Password store initialized for ${id_print%, }${id_path:+ ($id_path)}" git_add_file "$gpg_id" "Set GPG id to ${id_print%, }${id_path:+ ($id_path)}." + if [[ -n $PASSWORD_STORE_SIGNING_KEY ]]; then + local signing_keys=( ) key + for key in $PASSWORD_STORE_SIGNING_KEY; do + signing_keys+=( --default-key $key ) + done + gpg "${GPG_OPTS[@]}" "${signing_keys[@]}" --detach-sign "$gpg_id" || die "Could not sign .gpg_id." + key="$(gpg --verify --status-fd=1 "$gpg_id.sig" "$gpg_id" 2>/dev/null | sed -n 's/\[GNUPG:\] VALIDSIG [A-F0-9]\{40\} .* \([A-F0-9]\{40\}\)$/\1/p')" + [[ -n $key ]] || die "Signing of .gpg_id unsuccessful." + git_add_file "$gpg_id.sig" "Signing new GPG id with ${key//[$IFS]/,}." + fi fi reencrypt_path "$PREFIX/$id_path" @@ -578,6 +601,7 @@ cmd_extension() { local extension="$EXTENSIONS/$1.bash" check_sneaky_paths "$extension" if [[ -f $extension && -x $extension ]]; then + verify_file "$extension" shift source "$extension" "$@" else