Как заставить GPG принимать входные данные из STDIN вместо попытки открыть файл? - PullRequest
3 голосов
/ 08 августа 2011

Я пытаюсь включить в сценарий PHP четкую подпись текста GPG в строке. Я могу заставить 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"
}

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

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

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

Ответы [ 2 ]

5 голосов
/ 08 августа 2011

Вы можете использовать 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";
}
2 голосов
/ 08 августа 2011

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

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

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

...