使用GnuPG和C#自动解密文件
操作方法:自动化解密 PGP / GnuPG 加密文件。
引言
假设您需要解密并处理 PGP / GnuPG 加密的文件。本简短的操作指南希望能帮助您做到这一点。
背景
具体情况:我们的客户需要以安全的方式向我们提供通过 FTP 每天提供的 XML 文件。安全 FTP 不是一个选项,他们坚持使用 PGP。这没什么问题,对吧?实际上,却存在很多问题,我将尝试在这里帮助您避免这些问题。
显然,您需要安装 PGP 或其开源伙伴 GnuPG。您需要为自己创建私钥和公钥,并将公钥提供给“加密者”。所有这些内容在各种网站上都有充分的文档记录,因此我不再赘述。有一个名为“GNU Privacy Assistant”的不错的 Windows 应用程序(我使用的是 v0.5.0 版本),可以使这项工作快速而简单。在 Google 上搜索它,或通过 www.gnupg.org 获取它。
最终结果:一个人类无法读取的 / GPG 加密文档,现在需要由自动化流程解密和处理。
使用代码
我们使用的方法如下。基本上,从文件系统中获取您的加密文件,并通过 FileInfo
类获取对其的引用。将该引用传递给该方法。
private string DecryptFile(FileInfo encryptedFile)
{
// decrypts the file using GnuPG, saves it to the file system
// and returns the new (decrypted) file name.
// encrypted file: thefile.xml.gpg decrypted: thefile.xml
string outputFileName = this.GetDecryptedFileName(encryptedFile);
// whatever you want here - just a convention
string path = encryptedFile.DirectoryName;
string outputFileNameFullPath = path + "\\" + outputFileName;
try {
System.Diagnostics.ProcessStartInfo psi =
new System.Diagnostics.ProcessStartInfo("cmd.exe");
psi.CreateNoWindow = true;
psi.UseShellExecute = false;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.WorkingDirectory = "C:\\Program Files\\GnuPP\\GnuPG";
System.Diagnostics.Process process = System.Diagnostics.Process.Start(psi);
// actually NEED to set this as a local string variable
// and pass it - bombs otherwise!
string sCommandLine = "echo " + this._passphrase +
"| gpg.exe --passphrase-fd 0 -o \"" +
outputFileNameFullPath + "\" --decrypt \"" +
encryptedFile.FullName + "\"";
process.StandardInput.WriteLine(sCommandLine);
process.StandardInput.Flush();
process.StandardInput.Close();
process.WaitForExit();
process.Close();
}
catch (Exception ex)
{
this.HandleError(ex);
}
return outputFileName;
}
GetDecryptedFileName()
只是为生成的解密文件提供一个名称 - 其实现并不重要。基本上,只需从加密文件的末尾删除“.gpg”扩展名即可。该方法返回解密后的文件名以供进一步处理;同样,这并不重要,只是适合手头的任务。
有趣的部分:请注意,我们使用 System.Diagnostics.ProcessStartInfo
调用 Windows 命令 EXE。工作目录是存储 GnuPG 应用程序(EXE)和公钥和私钥文件的位置。
棘手的部分是将“秘密”密码和选项和命令通过 cmd.exe 传递给 gpg.exe 进程。这通过 System.Diagnostics.Process.StandardInput
完成。本质上,您正在启动一个命令窗口并向其提供类似以下内容:
C:\> echo my passphrase goes here| gpg.exe --passphrase-fd 0
-o "myDecryptedOutputFileName" --decrypt "myEncryptedFileName"
问题解决了!请注意,在像这样使用私钥密码的应用程序中存在安全问题 - 这是您的问题!对于我们的情况来说,这并不是一个大问题。
关注点
请注意“-o”选项?不要使用“-output”,它将不起作用。 另外请注意,我们如何在“sCommandLine
”中构建整个命令并将此变量传递给 WriteLine
? 这也很重要。由于某种原因,直接在 StandardInput.WriteLine()
中构建它也不起作用 - 可能是在 C# 中的转义字符。
希望这能帮助您避免我们在想出这个解决方案时遇到的挫折!