How can I 'echo' into fd 3 to be able to use it on a gpg cmd line?

omcujl92 at omcujl92 at
Fri Mar 29 02:37:36 CET 2024

, I now notice '<& Reads the input from one handle and writes it to
the output of another handle.' (Read from one, write to another.)

So 'echo %passphrase% <&3' would seem to input from stdin and output it to fd 3.
- I can’t think how to test this (under %COMSPEC%), though, and under
everything else it doesn’t matter. [If it doesn’t work there, there
are workarounds.]
- Under %COMSPEC%, file descriptors being broken – as below.

Answer / Solution: How can I 'echo' into fd 3 to be able to use it on
a gpg cmd line?

- [outside of %COMSPEC%], short answer: mkfifo myfifo; echo
%passphrase% > myfifo & ; echo data | gpg ... 3< myfifo; unset
passphrase ; rm myfifo.
- [inside of %COMSPEC%], short answer: you can’t (*). %COMSPEC% file
descriptors are broken. See thread ending at
- cygwin64 is gnupg unsupported, and cygwin32 is deprecated. See
for why.
 - even GnuWin (
[] is of no help, the root cause
being %COMPEC%, everything run therein remains broken (in this regard)
– at least in terms of pipelining file descriptors outside of 0, 1, 2
== ‘stdin, out, err’. So, for example, 3, 4, 5, 6, and beyond ==
‘stdwarn, verb, debug, info’ [per]
- use wsl, instead. []

(*) Afterward:
- Werner kindly appended to the
thread above, at,
indicating that a workaround for this %COMSPEC% issue will be included
in gnu2.6 – with the addition of a ‘--disable-fd-translation’ optional

(Proof of Concept) Goal (Reminder):
- echo secret data | gpg –pinentry-mode loopback –passphrase-fd 3 -c
3< $(echo %passphrase%) ; unset passphrase
[i.e. without any unencrypted data landing within your filesystems,
pipe your sensitive data directly into gpg, towards direct secure
storage. e.g. (web) BitWarden backup towards secure (local) storage
should BitWarden servers ever become incommunicado (e.g. broken wi-fi
or internet provider). BitWarden phones home before unlocking – if it
can’t get there, you’re S.O.L.
- Nevermind the duplicate functionality of gpg vs Bitwarden, this is a
backup, and Bitwarden offers turnkey cross-machine consistency out of
the gate.
- - But thank all that is holy for what GnuPG was, is, and will be.
You want to have both applications to hand.

Proof of Concept example script solutions:
@rem #! %COMSPEC%
@echo off
for /f "delims=" %%p in ('wsl /mnt/c/bin/gpggetpin.bash') do set
set /p "scratch=%GOTPASSPHRASE%" < nul:
#! /usr/bin/env bash

# gpggetpin.bash:
# GPG_TTY=$(tty) ; printf "GETPIN\n" | pinentry -T "${GPG_TTY}" | sed
-e "s/^OK.*$//" -e "/^[[:space:]]*$/d" -e "s/^D //"

bash -n "${0}" || true
shellcheck -W 0 -Calways "${0}" || true

# printf "getpin\n" | pinentry -g -T "$(tty)"    # - NOT HAPPY!

  declare -g  GPG_TERM ; GPG_TERM="${TERM}" ; export GPG_TERM
  declare -g  GPG_TTY ; GPG_TTY="$(tty)" ; export GPG_TTY
  declare -g  gs_passphrase="-1"
  declare -gi gi_0=-1

"$( \
printf "SETDESC My description\nSETPROMPT My prompt\nSETTITLE My
window title, iif there is a window\nGETPIN\nBYE\n" \
| pinentry --debug --ttyname "${GPG_TTY}" --ttytype "${GPG_TERM}"
--lc-ctype "en_ca.UTF-8" --lc-messages "en_ca.UTF-8" \
| sed -e "s/^OK.*$//" -e "/^[[:space:]]*$/d" -e "s/^D //" \

# USELESS - too many progs (retcodes) between source and end.
if false ; then
(( ! gi_0 )) && { printf "\n:: passphrase retrieval failed (%d),
exiting.\n\n" "${gi_0}" ; exit "${gi_0}" ; }
} ; fi

case "${gs_passphrase}" in
( "-1" );&
( "" );&
( "ERR 83886179 Operation cancelled <Pinentry>" )
# printf ":: no valid password retrieved (%d)[%d]. Exiting.\n\n"
"${gi_0}" "${#gs_passphrase}"
exit "${gi_0}"

#  printf ":: passphrase retrieved (%d)[%d].\n\n" "${gi_0}" "${#gs_passphrase}"
#  printf "\n|%s|\n\n" "${gs_passphrase}"

printf "%s" "${gs_passphrase}"

unset gs_passphrase
@rem #! %COMSPEC%
@echo off
wsl /mnt/c/bin/gpgtest.bash
#! /usr/bin/env bash
printf "\n"

set -vx

  declare -g gs_mysecretpassphrase="KXhtctw4_zFfhRop" # More usually
acquired somehow else.

  declare -g         gs_myfifo="$(mktemp -ut fifo.XXX)"
  mkfifo  -m 0600 "${gs_myfifo}"

  printf "%s" "${gs_mysecretpassphrase}" > "${gs_myfifo}" &

## Proof of concept, herein, being passphrase as passphrase being used
upon passphrase as data, encrypted to stdout.
## - $0 Caller redirecting stdout into desired destination filename.

  printf "%s" "${gs_mysecretpassphrase}" | gpg --pinentry-mode
loopback --passphrase-fd 3 -c 3< "${gs_myfifo}" ; printf "\n"

  rm "${gs_myfifo}"

set +xv

unset gs_mysecretpassphrase

On Mon, Mar 18, 2024 at 5:51 PM B.S. <bs27975 at> wrote:
> ... (Windows 10) [DOS] cmd ... [*NOT* powershell]
> ... cygwin gpg ...
> How can I 'echo' into fd 3 to be able to use it on a gpg cmd line?
> e.g. 'echo "Secret data" | gpg.exe -c -passphrase-fd 3 3< echo %PASSWORD%'
> [Ignore the need, or not, for --batch and/or --pinentry-mode loopback,
> I can wrestle with those separately.]
> (I am trying to avoid the passphrase from appearing in cleartext
> within tasklists, etc.)
> I am working on a BitWarden(-cli) backup script. So the 'echo "Secret
> data"' above is actually something like:
> bitwarden-cli --export json | gpg -c ... >...bitwarden_backup.json.pgp
> - the hangup seems to be how to echo into 3< to be able to use it as
> input, for ' -passphrase-fd 3'.
> [Or 7< echo %PASSWORD%, for that matter - it seems powershell uses 3-6
> for stdwarn|verbose|debug|info, and probably best to avoid potential
> future conflicts.]

More information about the Gnupg-users mailing list