2

我正在努力使用脚本更改GnuPG私钥密码。

据我所知:它返回该过程最终成功,但它不会更改密码。gpg的任何其他形式的选项都会导致错误并且不会更改密码。

有人有任何提示吗?无论是否使用 Symfony 的流程组件,我都会接受答案——我只需要让它工作。

也欢迎 Python/Bash/Expect 答案。它应该可以在不暴露命令行中的密码短语的情况下工作。

use Symfony\Component\Process\InputStream;
use Symfony\Component\Process\Process;

$fingerprint = '0123456789ABCDEF';
$previous = 'secret';
$passphrase = 'moresecret';

$process = new Process(
    [
        'gpg',
        '--passphrase-fd=0',
        '--pinentry-mode=loopback',
        '--change-passphrase',
        $fingerprint,
    ]
);

$input = new InputStream();
$process->setInput($input);

$process->start();

$input->write($previous."\n");
$input->write($passphrase."\n");
$input->close();

foreach ($process as $type => $data) {
    if ($process::OUT === $type) {
        echo "\nSTDOUT: $data";
    } else {
        echo "\nSTDERR: $data";
    }
}

return $process->isSuccessful();
4

1 回答 1

0

我设法让它与expectSymfony Process组件一起工作。

将此期望脚本保存在文件系统上:

#!/usr/bin/expect -f

spawn gpg --pinentry-mode=loopback --change-passphrase $env(GPG_USERID)
set timeout -1
expect "Enter passphrase: " { send "$env(GPG_PREVIOUS)\r" }
expect "Enter passphrase: " { send "$env(GPG_PASSPHRASE)\r" }
interact

使用以下代码执行并分析脚本运行的结果:

use Symfony\Component\Process\Process;

$userid = 'user@example.com';
$previous = 'secret';
$passphrase = 'moresecret';

$path = realpath(__DIR__ . '/path/to/your/script.exp');

$process = new Process(
    [
        $path,
    ],
    null,
    [
        'GPG_USERID' => $userid,
        'GPG_PREVIOUS' => $previous,
        'GPG_PASSPHRASE' => $passphrase,
    ]
);

$process->start();

$success = true;

$process->wait(function ($type, $buffer) use (&$success) {
    if (
        Process::OUT === $type
        && strpos($buffer, 'Bad passphrase') !== false
    ) {
        $success = false;
    }
});

return $process->isSuccessful() && $success;

即使前一个密码输入错误,gnupg也会返回退出代码 0。它在stdout上报告这一点,而不是在stderr上。

我解析输出寻找Bad passphrase并将其合并到最后的成功检查中。

我现在有一个完美的脚本更改密码短语方法,并且使用命令行参数不会影响安全性。

于 2019-12-29T02:04:37.820 回答