-
-
Notifications
You must be signed in to change notification settings - Fork 163
Description
The 1.4 release of gnupg is long time deprecated old and according to upstream shouldn't be used anymore (but it isn't EOL).
Various distros still have the package for compatibility reasons, but even Debian switched the name of the binary to gpg1. Even the case with Bullseye.
So in theory the majority should already use gpg2 as default.
Is there any distro around, which still ships gpg1 as gpg? (Hopefully not)
Reason being that it would allow to In my opinion we now can drop the gpg1 gnupg 1.4.11 specific workaround.
With that gone the gpg call could be restructured without worries about breaking something, as this early return is a nuisance.
What could be changed? There is still #304 around. And for the gpg call password and key are still combined via \n and piped into it.
There are in theory three options to retrieve a password with two being considered questionable
--passphrase-fd n
Read the passphrase from file descriptor n. Only the first line will
be read from file descriptor n. If you use 0 for n, the passphrase
will be read from STDIN. This can only be used if only one
passphrase is supplied. Note that this passphrase is only used if
the option --batch has also been given. This is different from gpg.
--passphrase-file file
Read the passphrase from file file. Only the first line will be read
from file file. This can only be used if only one passphrase is sup‐
plied. Obviously, a passphrase stored in a file is of questionable
security if other users can read this file. Don't use this option if
you can avoid it. Note that this passphrase is only used if the
option --batch has also been given. This is different from gpg.
--passphrase string
Use string as the passphrase. This can only be used if only one
passphrase is supplied. Obviously, this is of very questionable
security on a multi-user system. Don't use this option if you can
avoid it. Note that this passphrase is only used if the option
--batch has also been given. This is different from gpg.
The first is being used, the third would be the easiest. But without verifying if the password would appear in ps or whatnot it shouldn't be used :D
Another way would be to change the file descriptor for $password
The resulting function could look like this (untested):
gpg_decrypt() {
# gpgver could be removed if 2.0 if of no concern?
local gpgver=$(gpg --version --no-permission-warning | awk '/^gpg/ {print $3}')
local gpgpass="$1"
local tmpres ret
typeset -a gpgopt
gpgpopt=(--batch --no-tty --passphrase-fd 3 --no-options)
{ option_is_set -g } && {
gpgpass="$TOMBKEY"
gpgpopt=(--yes)
# GPG option '--try-secret-key' exist since GPG 2.1
{ option_is_set -R } && { autoload -U is-at-least && is-at-least "2.1" $gpgver } && {
typeset -a recipients
recipients=(${(s:,:)$(option_value -R)})
{ is_valid_recipients $recipients } || {
_failure "You set an invalid GPG ID."
}
gpgpopt+=(`_recipients_arg "--try-secret-key" $recipients`)
}
}
_tmp_create
tmpres=$TOMBTMP
TOMBSECRET=`print - "$TOMBKEY" | \
gpg --decrypt ${gpgpopt[@]} \
--status-fd 2 --no-mdc-warning --no-permission-warning \
--no-secmem-warning 3<<<"$gpgpass" 2> $tmpres`
unset gpgpass
ret=1
for i in ${(f)"$(cat $tmpres)"}; do
_verbose "$i"
[[ "$i" =~ "DECRYPTION_OKAY" ]] && ret=0;
done
return $ret
}Alternatively a anonymous pipe could be utilized in combination with --passphrase-file (untested):
gpg_decrypt() {
# again only needed if 2.0 is of concern
local gpgver=$(gpg --version --no-permission-warning | awk '/^gpg/ {print $3}')
local gpgpass="$1"
local tmpres ret
typeset -a gpgopt
gpgpopt=(--batch --no-tty --no-options)
{ option_is_set -g } && {
gpgpass="$TOMBKEY"
gpgpopt=(--yes)
# GPG option '--try-secret-key' exist since GPG 2.1
{ option_is_set -R } && { autoload -U is-at-least && is-at-least "2.1" $gpgver } && {
typeset -a recipients
recipients=(${(s:,:)$(option_value -R)})
{ is_valid_recipients $recipients } || {
_failure "You set an invalid GPG ID."
}
gpgpopt+=(`_recipients_arg "--try-secret-key" $recipients`)
}
}
_tmp_create
tmpres=$TOMBTMP
TOMBSECRET=`print - "$TOMBKEY" | \
gpg --decrypt ${gpgpopt[@]} \
--status-fd 2 --no-mdc-warning --no-permission-warning \
--no-secmem-warning --passphrase-file <(print -R -n - "$gpgpass") 2> $tmpres`
unset gpgpass
ret=1
for i in ${(f)"$(cat $tmpres)"}; do
_verbose "$i"
[[ "$i" =~ "DECRYPTION_OKAY" ]] && ret=0;
done
return $ret
}This will make the password available via a file descriptor (as an anonymous pipe normally as /dev/fd/63). The lifetime is bound to the runtime of gpg. And only gpg should be able to read or write from this location. And regarding the visibility: It should only show /dev/fd/63 in the process monitor tools.
Light testing via those commands:
$ zmodload zsh/mapfile
$ FILECONT=${mapfile[test.key]}
$ print - "$FILECONT" | gpg --decrypt --batch --no-tty --no-options --status-fd 0 --passphrase-file <(echo "test")
gpg: AES256.CFB verschlüsselte Daten
gpg: Verschlüsselt mit einem Passwort
(...)
$ print - "$FILECONT" | gpg --decrypt --batch --no-tty --no-options --status-fd 0 --passphrase-fd 3 3<<<"test"
gpg: AES256.CFB verschlüsselte Daten
gpg: Verschlüsselt mit einem Passwort
(...) But before looking further that, I would like to get rid of the restriction gpg1 :D
Edit: Some additional remarks for the POC section.
This is a pure zsh script, so it should use print instead of echo or printf (which also can have serious issues as I noticed).
Additionally zsh enables per default the interpretation of control sequences, opposit to bash. Therefore it would require echo -E or print -r.
And lastly: avoid adding a newline to the output (-n).
Need still to verify what redirect string does with control sequences.
Edit2: Reworded the proposal, as it doesn't remove the support for gnupg 1.4.x in general. It would only loose support for 1.4.11 which is really old and not the latest release of the 1.4.x series.
Additionally fix the snippets, as I got around testing them with tomb.