【问题标题】:GPG automatic decryption password passingGPG自动解密密码传递
【发布时间】:2015-04-13 10:57:49
【问题描述】:

我们从第三方接收 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);
}

【问题讨论】:

    标签: c# windows gnupg passphrase


    【解决方案1】:

    问题

    您正在使用 GnuPG 2,它只允许 --passphrase* 选项与 --batch 一起使用。

    使用--batch

    --passphrase* 选项用于编写脚本。 GnuPG 2 将它们(可能是为了慢慢弃用它们)限制为--batch 模式,其中 GnuPG 不执行任何交互(例如,询问您的密码或其他“对话”)。

    虽然这仍然可行,但最好使用 gpg-agent 中的密码预设,这样您就可以从应用程序代码中完全删除密码。请注意--passphrase(系统上的所有用户都可以读取它,只要 GnuPG 正在运行!)和--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

    gpg-preset-passphrase 是一个实用程序,用于为运行中的gpg-agent 的内部缓存提供密码短语。它主要适用于无人看管的机器,其中可能无法使用常用的pinentry 工具,并且在机器启动时会给出要使用的密钥的密码。

    [...]

    gpg-preset-passphrase 是这样调用的:

    gpg-preset-passphrase [options] [command] cacheid
    

    cacheid 是一个 40 个字符的十六进制字符键,用于标识应设置或清除密码的密钥。 [...]

    必须给出以下命令选项之一:

    --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# 写入进程的标准输入。

    【讨论】:

    • gpg2 绝对允许 --passphrase* 选项。但是,您必须指定 --batch 参数。
    • 你是对的。我似乎记错了限制,并修改了答案以使其准确。
    • --batch --passpharse abcxyz 在 Windows 命令行上效果很好,当我从指向 gpg 的 C# 进程调用它时它不起作用....
    • 我有同样的问题@RollRoll。你能解决这个问题吗?请分享您的修复。谢谢
    • 嘿,伙计,我解决了这个问题:您必须使用“批处理”语法解密,但如果它包含空格,您仍然无法在同一命令中传递密码短语(我在 { } 等之间的同一命令中尝试了不同的东西,但没有任何效果)。我通过使用这种“批量”解密命令语法并从 .txt 文件中获取密码来使其工作。不是最干净的,也不是最脏的。一旦我把代码拿回来给你看,我会尝试获取代码
    【解决方案2】:

    我尝试了接受的答案,但没有成功。

    我在Ubuntu 20.04.1 LTS

    检查我的answer,这对我有用

    【讨论】:

      猜你喜欢
      • 2017-10-08
      • 1970-01-01
      • 2011-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-23
      • 2016-05-29
      • 2021-07-12
      相关资源
      最近更新 更多