如何使用Gnupg的passphrase-fd参数?

33

我想在不需要用户交互的情况下使用GnuPG的decrypt命令。脚本的--passphrase-fd参数似乎正是我所需的。但我不知道它如何工作-没有找到示例。

请问有人能给我一个这样的命令示例,包括Windows和UNIX环境吗?

(FYI,我正在使用GnuPG 2)。

谢谢 :)

4个回答

51
为了在GnuPG v2中使用gpg选项--passphrase-fd,您必须指定--batch参数。我将首先解释--passphrase-fd的工作原理,然后再讲解示例。 --passphrase-fd告诉GnuPG应该从哪个文件描述符(-fd)中获取密码。标准文件描述符是STDIN(0)、STDOUT(1)和STDERR(2)。对于这个问题的上下文,您通常只需要关注STDIN(0)。
由于您没有指定想要从哪里获取密码,因此我将演示如何以各种方式使用STDIN(标准输入)来获取密码。 --passphrase-fd 0告诉GnuPG从当前shell的输入中检索密码;例如,如果您希望GnuPG在控制台的下一行获取密码数据,则命令和输出如下:
gpg2 --batch --passphrase-fd 0 --armor --decrypt /path/to/encrypted_file.pgp
<next line of input is passphrase followed by hitting enter>
gpg: encrypted with 1024-bit RSA key, ID EC18C175, created 2013-10-26
      "testkey4321 (4321) <test@4321.com>"
this is a test... this is only a test...

在上面的例子中,密码是通过文件描述符0(STDIN)提供的 - 我们通过在shell的当前标准输入上输入它来提供。
在下一个示例中,我们将告诉GnuPG从当前shell的输入中检索密码,实际上是另一个命令(例如echo,它只是“回显”您告诉它的内容)的输出。
echo "mypassphrase" | gpg2 --batch --passphrase-fd 0 --armor --decrypt /path/to/encrypted_file.pgp
gpg: encrypted with 1024-bit RSA key, ID EC18C175, created 2013-10-26
      "testkey4321 (4321) <test@4321.com>"
this is a test... this is only a test...

另一个例子是将包含口令的文件内容转储到 STDIN 中 -

cat /path/to/file_with_passphrase | gpg2 --batch --passphrase-fd 0 --armor --decrypt /path/to/encrypted_file.pgp
gpg: encrypted with 1024-bit RSA key, ID EC18C175, created 2013-10-26
      "testkey4321 (4321) <test@4321.com>"
this is a test... this is only a test...

总之,--passphrase-fd只是告诉GnuPG您想通过标准文件描述符提供必要的密码;GnuPG v2和GnuPG之间的区别仅在于--batch参数。
上述示例在Windows和*nix环境中应该都可以正常工作,唯一的区别是在Windows中,根据您的配置和版本,您将不得不使用type替换cat以将文件内容转储到STDIN。

1
太好了!非常感谢您挖掘我的问题并提供答案! - Blackbird
1
谢谢,这正是我在寻找的信息。 - dchayka
我无法在Windows上使用“type”或“echo”命令使其工作。有效的方法是将口令放入文件中,并将该文件推送到gpg2。因此,命令如下:gpg2 --batch --passphrase-fd 0 --decrypt "filetodecrypturi" < "filewithpassphraseuri" - Dolfa
@Dolfa:非常感谢……你不知道我在 Windows 上尝试了多少次使用 echo 命令......你的命令确实帮了我很大的忙。 - Viji
echo "mypassphrase" | gpg2 --batch --passphrase-fd 0 通过从文件描述符中读取口令来提高安全性的目的被破坏了,如果 echo 是一个独立的命令,因为这样口令又成为了公共命令行参数的一部分。最好使用 <<< 运算符来防止任何意外的密码泄漏。 - ceving
当使用 --passphrase-fd 0 时,如何通过命令行提供要加密的内容? - sunknudsen

25

kylehuff的答案对我仍然无效,gpupg仍会弹出密码提示。

根据https://wiki.archlinux.org/index.php/GnuPG#Unattended_passphrase所述,如果使用gnupg 2.1.0及更高版本,则需要执行其他步骤才能支持--passphrase-fd参数。

First, edit the gpg-agent configuration to allow loopback pinentry mode: ~/.gnupg/gpg-agent.conf

allow-loopback-pinentry

Restart the gpg-agent process if it is running to let the change take effect.

Second, either the application needs to be updated to include a commandline parameter to use loopback mode like so:

$ gpg --pinentry-mode loopback ...

2
谢谢,谢谢,谢谢,谢谢,谢谢!我为了这个问题已经挣扎了好几个小时,直到看到你的答案时才发现需要这么做! - ibrewster
1
请注意,allow-loopback-pinentry 实际上默认已启用。不确定为什么 Arch Wiki 如此明确地提到它。来源:https://www.gnupg.org/documentation/manuals/gnupg/Agent-Options.html - jlh
谢谢@JodiTheTigger,我已经寻找这个答案有一段时间了! - aceinthehole
1
最后,好了。为了验证,在Win7 gpg 2.2.4上,这个命令是有效的:echo thepassword|gpg --pinentry-mode loopback --batch --passphrase-fd 0 --decrypt-files *.pgp - Slashback

7

使用GPG4win/gpg 2.2.3:要使用passphrase-fd 0并绕过提示,我可以确认以下操作是有效的:

--pinentry-mode loopback

4

作为最近自己不得不弄清楚这个问题的人,我认为值得略微介入。

kylehuff的答案非常好,如果你要解密文件,但是,如果你需要输入/输出重定向,例如管道,请看一个使用非0文件描述符传递密码的例子。

#!/usr/bin/env bash
# Set some variables for easy modding
Var_fd='9'
Var_pass_location="/path/to/passphrase.file"
Var_gpg_decrypt_opts="--passphrase-fd ${Var_fd} --decrypt"
Var_output_location="out.txt"
Arr_string=( "$@" )
# Open file descriptor and shove the passphrase file into it
exec ${Var_fd}<${Var_pass_location}
# Pipe input array though gpg and append to output file
cat <<<"${Arr_string[*]}" | $(which gpg) ${Var_gpg_decrypt_opts} >> ${Var_output_location}
# Do not forget to close the file descriptor
exec ${Var_fd}>&-

请注意,在特殊情况下以外,保存您的私钥密码短语通常被视为不好的想法或不良的安全实践。-另外,请不要忘记在完成后关闭描述符,以便您的密码短语不再通过该方法访问。-在这些用例中经常建议使用专门的非密码保护密钥,但这完全取决于您的选择。如果您喜欢上面的代码,则可能还需要检查我为密钥生成调试的脚本,无论是自动还是手动,因为它甚至涵盖了更不常用的gpg文件描述符选项。
编辑/更新
所以我一直在调试大量解密操作,并且有证据表明文件描述符似乎会自动关闭,或者可能是由GnuPG自动关闭的。检查构建152,在原始日志的底部,就在diff检查之前,您会发现第一个加密数据块吞掉了密码短语,导致下面两个数据块没有有效的密码短语。此操作中的相关脚本为:首先,script_decrypt.sh构建脚本将测试密钥的密码短语设置为文件描述符9,如上面的示例所示,然后调用Helper script,使其利用该文件描述符……这是一个有趣的用例,但故事的寓意似乎是,您计划使用GnuPG文件描述符进行的任何大量解密操作都可能需要按照以上步骤作为整个函数来正确重新打开文件描述符。在未来的几次推送中,我将重写助手脚本,因此请检查大于152Travis-CI构建日志,以查找文件描述符关闭的解决方案……
……所以这只花了两次尝试才能让事情正常工作,请参见构建154中的差异,加密文件和原始输入日志匹配。正如假设的那样,文件描述符在第一次使用后被GnuPG或子shell转储,因此需要在每个解密命令之前分配密码短语才能进行大量解密。
希望这对您有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接