Как заставить GPG принимать входные данные от STDIN вместо попытки открыть файл?

Я пытаюсь включить прозрачное подписание текста GPG в строке в скрипте PHP. Я могу заставить GPG шифровать текст в строке следующим образом:

$encrypted = shell_exec("echo '$text' | gpg -e -a -r foo@bar.com --trust-model always"); 

и это работает отлично, при этом зашифрованный текст отправляется в переменную $ encrypted. Это доказывает правильность настройки GNUPGHOME и GNUPG.

Однако, когда я пытаюсь создать сообщение с четким сообщением таким же образом:

 $text = "googar"; $signature = exec("echo $passphrase | gpg -v --clearsign --no-tty --passphrase-fd 0 '$text' 2>&1 1> /dev/null", $output); 

Я возвращаю эту ошибку:

 ... string(51) "gpg: can't open `googar': No such file or directory" [3]=> string(46) "gpg: googar: clearsign failed: file open error" } 

Эта ошибка возвращается с или без одинарных кавычек вокруг текстовой переменной $.

Как заставить GPG или shell_exec обрабатывать $ text как канал вместо поиска файла?

Мне нужно эхо кодовую фразу таким образом (я знаю, его «ужасно небезопасно», потому что GPG не имеет возможности передавать в качестве ключевой фразы в качестве переменной в командной строке.

Вы можете использовать proc_open и создать отдельный дескриптор файла для вашего пароля:

 $descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w"), 3 => array("pipe", "r"), ); $pipes = false; $process = proc_open("gpg -v --clearsign --no-tty --passphrase-fd 3", $descriptorspec, $pipes); if(is_resource($process)) { fwrite($pipes[3], $passphrase); fclose($pipes[3]); fwrite($pipes[0], $text); fclose($pipes[0]); $output = stream_get_contents($pipes[1]); $stderr = stream_get_contents($pipes[2]); fclose($pipes[1]); fclose($pipes[2]); $retval = proc_close($process); echo "retval = $retval\n"; echo "output= $output\n"; echo "err= $stderr\n"; } 

Вы можете использовать замену процесса:

 echo $passphrase | gpg -v --clearsign --no-tty --passphrase-fd 0 <(printf '$text') 2>&1 1> /dev/null ^^ ^ 

Это заставит gpg думать, что он считывает данные из файла, но файл будет временным именованным каналом, для ввода которого будет printf '$text' .