GPG自动解密密码传递
GPG automatic decryption password passing
我们从第三方接收 GPG 加密文件。我正在修改一个 C# 程序来查找加密文件、解密它们并删除加密文件。除了在解密部分提示输入密码外,这一切都有效;我知道密码,输入后即可使用。我需要在命令中传递密码,这样提示就不会出现了。
string CommandText = string.Format("echo {0}|gpg.exe --keyring {1} --secret-keyring {2} --batch --yes --passphrase-fd 0 -o {3} -d {4}",
passPhrase, publicKeyRingPath, secretKeyRingPath, outputFullPath, encryptedFilePath);
我也试过:
string CommandText = string.Format("gpg.exe --keyring {1} --secret-keyring {2} --batch --yes --passphrase {0} -o {3} -d {4}",
string CommandText = string.Format("gpg.exe --keyring {1} --secret-keyring {2} --batch --yes --passphrase-fd {0} -o {3} -d {4}",
以及其他几个变体。
这是 运行 GnuPG for Windows 2.1.0.57899
如果问题出在其他地方,这里有一堆主要由我的前任编写的代码:
public bool decryptInputFile(string encryptedFilePath, string outputFullPath, out string message)
{
message = "decryptInputFile: Started";
try
{
ProcessStartInfo psi = new ProcessStartInfo("cmd.exe")
{
CreateNoWindow = true,
UseShellExecute = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
WorkingDirectory = decryptPath,
};
message = "decryptInputFile: PSI Initialized";
using (Process process = Process.Start(psi))
{
string CommandText = string.Format("echo {0}|gpg.exe --keyring {1} --secret-keyring {2} --batch --yes --passphrase-fd 0 -o {3} -d {4}",
passPhrase, publicKeyRingPath, secretKeyRingPath, outputFullPath, encryptedFilePath);
process.StandardInput.WriteLine(CommandText);
process.StandardInput.Flush();
process.StandardInput.Close();
process.WaitForExit();
process.Close();
process.Dispose();
message = "decryptInputFile: Success";
//These processes don't close and it keeps the file from being deleted.
foreach (Process P in Process.GetProcessesByName("gpg")) { P.Kill(); }
foreach (Process P in Process.GetProcessesByName("gpg2")) { P.Kill(); }
}
}
catch (Exception x)
{
// If there was an error, we're going to eat it and just let the user know we failed.
message = "decryptInputFile: Error: " + x.Message;
string errMessage = "ERROR: could not decrypt. " + x.Message + "\r\n";
File.AppendAllText(System.Configuration.ConfigurationSettings.AppSettings["LogPath"], errMessage);
return false;
}
if (File.Exists(outputFullPath) && File.Exists(encryptedFilePath))
{
File.Delete(encryptedFilePath);
}
return File.Exists(outputFullPath);
}
问题
您使用的是 GnuPG 2,它只允许 --passphrase*
选项和 --batch
。
使用--batch
--passphrase*
选项用于编写脚本。 GnuPG 2 将它们限制在 --batch
模式(可能是为了慢慢弃用它们),在这种模式下 GnuPG 不执行任何交互(例如,询问您的密码或其他“对话”)。
虽然这仍然可行,但最好使用 gpg-agent
中的密码预设,这样您就可以从应用程序代码中完全删除密码。注意--passphrase
(你系统上的所有用户都可以读取它,只要GnuPG是运行ning!)和--passphrase-file
(密码存储在硬盘上,注意权限)。
预设密码
GnuPG 2 的首选方法是在 gpg-agent
中预设密码,GnuPG 非常依赖它;在 GnuPG 2.1 的情况下,甚至可以完全自行处理私钥和密码操作。
但是,为了拯救您,GnuPG 2 带来了一个新工具,gpg-preset-passphrase
。在 Debian Linux 上,它隐藏在 /usr/lib/gnupg2/
中,我不知道它存储在 Windows.
中的什么地方
来自man gpg-preset-passphrase
:
The gpg-preset-passphrase
is a utility to seed the internal cache of a running gpg-agent
with passphrases. It is mainly useful for unattended machines, where the usual pinentry
tool may not be used and the passphrases for the to be used keys are given at machine startup.
[...]
gpg-preset-passphrase
is invoked this way:
gpg-preset-passphrase [options] [command] cacheid
cacheid
is either a 40 character keygrip of hexadecimal characters identifying the key for which the passphrase should be set or cleared. [...]
One of the following command options must be given:
--preset
Preset a passphrase. This is what you usually will use.
gpg-preset-passphrase will then read the passphrase from stdin.
最后,在为您的应用程序初始化 GnuPG 时(并在与配置的缓存时间相对应的时间间隔内)运行 gpg-preset-passphrase --preset [fingerprint]
,这将从标准输入读取密码,或者另外使用 --passphrase passphrase
选项直接在您的查询中设置它。请注意,当同时使用 echo 或 --passphrase
方法时,其他系统用户可能会通过列出进程来获取密码;最好直接从 C# 写入进程的标准输入。
我尝试了接受的答案,但没有成功。
我在 Ubuntu 20.04.1 LTS
检查我的 answer 对我有用
我们从第三方接收 GPG 加密文件。我正在修改一个 C# 程序来查找加密文件、解密它们并删除加密文件。除了在解密部分提示输入密码外,这一切都有效;我知道密码,输入后即可使用。我需要在命令中传递密码,这样提示就不会出现了。
string CommandText = string.Format("echo {0}|gpg.exe --keyring {1} --secret-keyring {2} --batch --yes --passphrase-fd 0 -o {3} -d {4}",
passPhrase, publicKeyRingPath, secretKeyRingPath, outputFullPath, encryptedFilePath);
我也试过:
string CommandText = string.Format("gpg.exe --keyring {1} --secret-keyring {2} --batch --yes --passphrase {0} -o {3} -d {4}",
string CommandText = string.Format("gpg.exe --keyring {1} --secret-keyring {2} --batch --yes --passphrase-fd {0} -o {3} -d {4}",
以及其他几个变体。
这是 运行 GnuPG for Windows 2.1.0.57899
如果问题出在其他地方,这里有一堆主要由我的前任编写的代码:
public bool decryptInputFile(string encryptedFilePath, string outputFullPath, out string message)
{
message = "decryptInputFile: Started";
try
{
ProcessStartInfo psi = new ProcessStartInfo("cmd.exe")
{
CreateNoWindow = true,
UseShellExecute = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
WorkingDirectory = decryptPath,
};
message = "decryptInputFile: PSI Initialized";
using (Process process = Process.Start(psi))
{
string CommandText = string.Format("echo {0}|gpg.exe --keyring {1} --secret-keyring {2} --batch --yes --passphrase-fd 0 -o {3} -d {4}",
passPhrase, publicKeyRingPath, secretKeyRingPath, outputFullPath, encryptedFilePath);
process.StandardInput.WriteLine(CommandText);
process.StandardInput.Flush();
process.StandardInput.Close();
process.WaitForExit();
process.Close();
process.Dispose();
message = "decryptInputFile: Success";
//These processes don't close and it keeps the file from being deleted.
foreach (Process P in Process.GetProcessesByName("gpg")) { P.Kill(); }
foreach (Process P in Process.GetProcessesByName("gpg2")) { P.Kill(); }
}
}
catch (Exception x)
{
// If there was an error, we're going to eat it and just let the user know we failed.
message = "decryptInputFile: Error: " + x.Message;
string errMessage = "ERROR: could not decrypt. " + x.Message + "\r\n";
File.AppendAllText(System.Configuration.ConfigurationSettings.AppSettings["LogPath"], errMessage);
return false;
}
if (File.Exists(outputFullPath) && File.Exists(encryptedFilePath))
{
File.Delete(encryptedFilePath);
}
return File.Exists(outputFullPath);
}
问题
您使用的是 GnuPG 2,它只允许 --passphrase*
选项和 --batch
。
使用--batch
--passphrase*
选项用于编写脚本。 GnuPG 2 将它们限制在 --batch
模式(可能是为了慢慢弃用它们),在这种模式下 GnuPG 不执行任何交互(例如,询问您的密码或其他“对话”)。
虽然这仍然可行,但最好使用 gpg-agent
中的密码预设,这样您就可以从应用程序代码中完全删除密码。注意--passphrase
(你系统上的所有用户都可以读取它,只要GnuPG是运行ning!)和--passphrase-file
(密码存储在硬盘上,注意权限)。
预设密码
GnuPG 2 的首选方法是在 gpg-agent
中预设密码,GnuPG 非常依赖它;在 GnuPG 2.1 的情况下,甚至可以完全自行处理私钥和密码操作。
但是,为了拯救您,GnuPG 2 带来了一个新工具,gpg-preset-passphrase
。在 Debian Linux 上,它隐藏在 /usr/lib/gnupg2/
中,我不知道它存储在 Windows.
来自man gpg-preset-passphrase
:
The
gpg-preset-passphrase
is a utility to seed the internal cache of a runninggpg-agent
with passphrases. It is mainly useful for unattended machines, where the usualpinentry
tool may not be used and the passphrases for the to be used keys are given at machine startup.[...]
gpg-preset-passphrase
is invoked this way:gpg-preset-passphrase [options] [command] cacheid
cacheid
is either a 40 character keygrip of hexadecimal characters identifying the key for which the passphrase should be set or cleared. [...]One of the following command options must be given:
--preset Preset a passphrase. This is what you usually will use. gpg-preset-passphrase will then read the passphrase from stdin.
最后,在为您的应用程序初始化 GnuPG 时(并在与配置的缓存时间相对应的时间间隔内)运行 gpg-preset-passphrase --preset [fingerprint]
,这将从标准输入读取密码,或者另外使用 --passphrase passphrase
选项直接在您的查询中设置它。请注意,当同时使用 echo 或 --passphrase
方法时,其他系统用户可能会通过列出进程来获取密码;最好直接从 C# 写入进程的标准输入。
我尝试了接受的答案,但没有成功。
我在 Ubuntu 20.04.1 LTS
检查我的 answer 对我有用