#region Disclaimer / License // Copyright (C) 2008, Kenneth Skovhede // http://www.hexad.dk, opensource@hexad.dk // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // #endregion using System; using System.Collections.Generic; using System.Text; using System.IO; namespace Duplicati.Library.Encryption { /// /// Implements a encryption/decryption with the GNU Privacy Guard (GPG) /// public class GPGEncryption : EncryptionBase, IEncryption { /// /// The PGP program to use, should be with absolute path /// public static string PGP_PROGRAM = "pgp"; /// /// Always present commandline args /// private const string COMMANDLINE_ARGS = "--symmetric --armor"; /// /// Commandline switches for encryption /// private const string ENCRYPTION_ARGS = "--encrypt"; /// /// Commandline switches for decryption /// private const string DECRYPTION_ARGS = "--decrypt"; /// /// The key used for cryptographic operations /// private string m_key; /// /// An optional key, used for signature verification /// private string m_signaturekey; /// /// Constructs a new instance of the PGP encryption/decryption class. /// /// The key used to encrypt/decrypt data /// The key used to generate a signature with (currently unused) public GPGEncryption(string key, string signaturekey) { m_key = key; m_signaturekey = signaturekey; } #region IEncryption Members public override void Encrypt(System.IO.Stream input, System.IO.Stream output) { this.Execute(COMMANDLINE_ARGS + " " + ENCRYPTION_ARGS, input, output); } public override void Decrypt(System.IO.Stream input, System.IO.Stream output) { this.Execute(COMMANDLINE_ARGS + " " + DECRYPTION_ARGS, input, output); } /// /// Internal helper that wraps GPG usage /// /// The commandline arguments /// The input stream /// The output stream private void Execute(string args, System.IO.Stream input, System.IO.Stream output) { System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(); psi.Arguments = args; psi.CreateNoWindow = true; psi.FileName = PGP_PROGRAM; psi.RedirectStandardError = true; psi.RedirectStandardInput = true; psi.RedirectStandardOutput = true; psi.UseShellExecute = false; psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; System.Diagnostics.Process p = System.Diagnostics.Process.Start(psi); p.StandardInput.WriteLine(m_key); //Prevent blocking of the output buffer System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(Runner)); t.Start(new object[] {p.StandardOutput.BaseStream, output}); //Copy input stream to GPG Core.Utility.CopyStream(input, p.StandardInput.BaseStream); p.StandardInput.Close(); if (!t.Join(5000)) throw new Exception("Failure while invoking GnuPG, program won't flush output"); if (!p.WaitForExit(5000)) throw new Exception("Failure while invoking GnuPG, program won't terminate"); } private void Runner(object x) { //Unwrap arguments and read stream object[] tmp = (object[])x; Core.Utility.CopyStream((Stream)tmp[0], (Stream)tmp[1]); } #endregion } }