4

我正在尝试将 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"
}

带有或不带有 $text 变量周围的单引号都会返回此错误。

如何强制 GPG 或 shell_exec 将 $text 视为管道而不是查找文件?

我需要以这种方式回显密码(我知道,它“非常不安全”,因为 GPG 无法在命令行上将密码作为变量传递。

4

2 回答 2

5

您可以使用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";
}
于 2011-08-08T13:35:59.950 回答
2

您可以使用流程替换:

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

这将使 gpg 认为它正在从文件中读取数据,但该文件将是一个临时命名管道,其输入将是printf '$text'.

于 2011-08-08T13:20:17.827 回答