[pass] [PATCH 1/2] init: respect multiple subkeys during reencryption
duncankburke at gmail.com
duncankburke at gmail.com
Sat Sep 20 08:58:34 CEST 2014
From: Duncan Burke <duncankburke at gmail.com>
In the case where an identity has multiple subkeys for encryption, reencryption
was partially broken. To prevent unnecessary reencryption, the current keys
for a file are compared with the expected keys for a given gpg id. This requires
the means to translate a gpg id into a normalised long keyid.
By default, passing the id of a particular subkey as a recipient does not
necessarily cause gpg to encrypt with that key, rather, gpg takes the
parent identity and chooses a subkey independently. From the code in the function
gpgsm_add_to_certlist (gnupg/sm/certlist.c), it appears gpg simply takes the
last subkey in the list with the encryption flag set. gpg can be forced to use
a specific encryption key by appending '!' to the end of the key id.
For example:
pub 4096R/4A241115 2014-04-26 [expires: 2018-09-18]
sub 4096R/D132D31E 2014-09-19
sub 2048R/8CD8DCB7 2014-09-19
Both D132D31E and 8CD8DCB7 have the encryption flag set.
$ pass init 4A241115
$ pass generate foo 12
$ pass generate dir/bar 12
$ gpg -v --list-only .password-store/foo.gpg
Version: GnuPG v2
gpg: armor header:
gpg: public key is 8CD8DCB7
$ pass init D132D31E
Password store initialized for D132D31E
$ pass init D132D31E!
Password store initialized for D132D31E!
dir/bar: reencrypting to 2698F2A9D132D31E
foo: reencrypting to 2698F2A9D132D31E
$ pass init -p dir D132D31E! 8CD8DCB7!
Password store initialized for D132D31E!, 8CD8DCB7!
dir/bar: reencrypting to 2698F2A9D132D31E 71B10D108CD8DCB7
$ pass generate dir/foobar 12
$ gpg -v --list-only .password-store/dir/foobar.gpg
Version: GnuPG v2
gpg: armor header:
gpg: public key is D132D31E
gpg: public key is 8CD8DCB7
Signed-off-by: Duncan Burke <duncankburke at gmail.com>
---
src/password-store.sh | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/src/password-store.sh b/src/password-store.sh
index 2287a46..cf57fd3 100755
--- a/src/password-store.sh
+++ b/src/password-store.sh
@@ -108,7 +108,20 @@ reencrypt_path() {
IFS=";" eval 'GPG_RECIPIENTS+=( $group )' # http://unix.stackexchange.com/a/92190
unset GPG_RECIPIENTS[$index]
done
- gpg_keys="$($GPG --list-keys --keyid-format long "${GPG_RECIPIENTS[@]}" | sed -n 's/sub *.*\/\([A-F0-9]\{16\}\) .*/\1/p' | LC_ALL=C sort -u)"
+ gpg_keys=""
+ for index in "${!GPG_RECIPIENTS[@]}"; do
+ local key_list="$GPG --list-keys --keyid-format long --with-colons ${GPG_RECIPIENTS[$index]}"
+ if [[ ${GPG_RECIPIENTS[$index]: -1} == "!" ]]; then
+ # The exact subkey is specified
+ local gpg_id="$(tr '[:lower:]' '[:upper:]' <<< ${GPG_RECIPIENTS[index]%!})"
+ gpg_keys+=$(${key_list} | sed -n "s/^sub:\\([^:]*:\\)\\{3\\}\\([^:]*${gpg_id}\\):.*$/\\2 /p" | head -n 1)
+ else
+ # gnupg takes the last subkey with encryption enabled
+ # see gpgsm_add_to_certlist (gnupg/sm/certlist.c)
+ gpg_keys+=$(${key_list} | sed -n "s/^sub:\\([^:]*:\\)\\{3\\}\\([^:]*\\):\\([^:]*:\\)\\{6\\}e:$/\\2 /p" | tail -n 1)
+ fi
+ done
+ gpg_keys="$(printf "%s\n" ${gpg_keys[*]} | LC_ALL=C sort -u)"
fi
current_keys="$($GPG -v --no-secmem-warning --no-permission-warning --list-only --keyid-format long "$passfile" 2>&1 | cut -d ' ' -f 5 | LC_ALL=C sort -u)"
--
2.0.0
More information about the Password-Store
mailing list