Added basic cryptography support.
git-svn-id: https://duplicati.googlecode.com/svn/trunk@52 59da171f-624f-0410-aa54-27559c288bec
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Duplicati.Encryption
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements AES encryption
|
||||
/// </summary>
|
||||
public class AESEncryption : EncryptionBase, IEncryption
|
||||
{
|
||||
/// <summary>
|
||||
/// The AES instance
|
||||
/// </summary>
|
||||
private System.Security.Cryptography.Rijndael m_instance;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new AES encryption/decyption instance
|
||||
/// </summary>
|
||||
/// <param name="key">The key used for encryption. The key gets stretched through SHA hashing to fit the key size requirements</param>
|
||||
public AESEncryption(string key)
|
||||
{
|
||||
m_instance = System.Security.Cryptography.Rijndael.Create();
|
||||
System.Security.Cryptography.SHA256 sha = System.Security.Cryptography.SHA256.Create();
|
||||
int len = m_instance.IV.Length + m_instance.Key.Length;
|
||||
System.IO.MemoryStream ms = new System.IO.MemoryStream();
|
||||
|
||||
//We stretch the key material by issuing cascading hash operations.
|
||||
//This somewhat alters the characteristics of the key, but as long
|
||||
//as the hashing is cryptographically safe and does not induce aliasing
|
||||
//with the encryption, it does not reduce the strength of the encryption
|
||||
byte[] tmp = System.Text.Encoding.UTF8.GetBytes(key);
|
||||
while (ms.Length < len)
|
||||
{
|
||||
if (!sha.CanReuseTransform)
|
||||
sha = System.Security.Cryptography.SHA256.Create();
|
||||
sha.Initialize();
|
||||
|
||||
tmp = sha.ComputeHash(tmp);
|
||||
ms.Write(tmp, 0, (int)Math.Min(tmp.Length, len - ms.Length));
|
||||
}
|
||||
|
||||
byte[] realkey = new byte[m_instance.Key.Length];
|
||||
byte[] iv = new byte[m_instance.IV.Length];
|
||||
ms.Position = 0;
|
||||
if (ms.Read(iv, 0, iv.Length) != iv.Length)
|
||||
throw new Exception("Bad key stretch");
|
||||
if (ms.Read(realkey, 0, realkey.Length) != realkey.Length)
|
||||
throw new Exception("Bad key stretch");
|
||||
ms.Dispose();
|
||||
|
||||
m_instance.IV = iv;
|
||||
m_instance.Key = realkey;
|
||||
m_instance.Mode = System.Security.Cryptography.CipherMode.CBC;
|
||||
}
|
||||
|
||||
#region IEncryption Members
|
||||
|
||||
public override void Encrypt(System.IO.Stream input, System.IO.Stream output)
|
||||
{
|
||||
if (m_instance.Mode == System.Security.Cryptography.CipherMode.ECB)
|
||||
throw new Exception("Useless encryption detected");
|
||||
|
||||
System.Security.Cryptography.ICryptoTransform ct = m_instance.CreateEncryptor();
|
||||
using (System.Security.Cryptography.CryptoStream cs = new System.Security.Cryptography.CryptoStream(input, ct, System.Security.Cryptography.CryptoStreamMode.Write))
|
||||
Core.Utility.CopyStream(cs, output);
|
||||
}
|
||||
|
||||
public override void Decrypt(System.IO.Stream input, System.IO.Stream output)
|
||||
{
|
||||
if (m_instance.Mode == System.Security.Cryptography.CipherMode.ECB)
|
||||
throw new Exception("Useless encryption detected");
|
||||
|
||||
System.Security.Cryptography.ICryptoTransform ct = m_instance.CreateDecryptor();
|
||||
using (System.Security.Cryptography.CryptoStream cs = new System.Security.Cryptography.CryptoStream(input, ct, System.Security.Cryptography.CryptoStreamMode.Read))
|
||||
Core.Utility.CopyStream(cs, output);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>8.0.50727</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{94484FDB-2EFA-4CF0-9BE6-A561157B4F87}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Duplicati.Encryption</RootNamespace>
|
||||
<AssemblyName>Duplicati.Encryption</AssemblyName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AESEncryption.cs" />
|
||||
<Compile Include="EncryptionBase.cs" />
|
||||
<Compile Include="IEncryption.cs" />
|
||||
<Compile Include="GPGEncryption.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Core\Duplicati.Core.csproj">
|
||||
<Project>{DE3E5D4C-51AB-4E5E-BEE8-E636CEBFBA65}</Project>
|
||||
<Name>Duplicati.Core</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Duplicati.Encryption
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple helper class that implements the filebased functions, and wraps them onto the stream based ones
|
||||
/// </summary>
|
||||
public abstract class EncryptionBase : IEncryption
|
||||
{
|
||||
#region IEncryption Members
|
||||
|
||||
public virtual void Encrypt(string inputfile, string outputfile)
|
||||
{
|
||||
using (System.IO.FileStream fs1 = System.IO.File.OpenRead(inputfile))
|
||||
using (System.IO.FileStream fs2 = System.IO.File.Create(outputfile))
|
||||
this.Encrypt(fs1, fs2);
|
||||
}
|
||||
|
||||
public abstract void Encrypt(System.IO.Stream input, System.IO.Stream output);
|
||||
|
||||
public virtual void Decrypt(string inputfile, string outputfile)
|
||||
{
|
||||
using (System.IO.FileStream fs1 = System.IO.File.OpenRead(inputfile))
|
||||
using (System.IO.FileStream fs2 = System.IO.File.Create(outputfile))
|
||||
this.Decrypt(fs1, fs2);
|
||||
}
|
||||
|
||||
public abstract void Decrypt(System.IO.Stream input, System.IO.Stream output);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace Duplicati.Encryption
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements a encryption/decryption with the GNU Privacy Guard (GPG)
|
||||
/// </summary>
|
||||
public class GPGEncryption : EncryptionBase, IEncryption
|
||||
{
|
||||
/// <summary>
|
||||
/// The PGP program to use, should be with absolute path
|
||||
/// </summary>
|
||||
public static string PGP_PROGRAM = "pgp";
|
||||
|
||||
/// <summary>
|
||||
/// Always present commandline args
|
||||
/// </summary>
|
||||
private const string COMMANDLINE_ARGS = "--symmetric --armor";
|
||||
|
||||
/// <summary>
|
||||
/// Commandline switches for encryption
|
||||
/// </summary>
|
||||
private const string ENCRYPTION_ARGS = "--encrypt";
|
||||
|
||||
/// <summary>
|
||||
/// Commandline switches for decryption
|
||||
/// </summary>
|
||||
private const string DECRYPTION_ARGS = "--decrypt";
|
||||
|
||||
/// <summary>
|
||||
/// The key used for cryptographic operations
|
||||
/// </summary>
|
||||
private string m_key;
|
||||
|
||||
/// <summary>
|
||||
/// An optional key, used for signature verification
|
||||
/// </summary>
|
||||
private string m_signaturekey;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new instance of the PGP encryption/decryption class.
|
||||
/// </summary>
|
||||
/// <param name="key">The key used to encrypt/decrypt data</param>
|
||||
/// <param name="signaturekey">The key used to generate a signature with (currently unused)</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal helper that wraps GPG usage
|
||||
/// </summary>
|
||||
/// <param name="args">The commandline arguments</param>
|
||||
/// <param name="input">The input stream</param>
|
||||
/// <param name="output">The output stream</param>
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace Duplicati.Encryption
|
||||
{
|
||||
/// <summary>
|
||||
/// Public interface for an encryption method
|
||||
/// </summary>
|
||||
public interface IEncryption
|
||||
{
|
||||
/// <summary>
|
||||
/// Encrypts the contents of the inputfile, and saves the result as the outputfile.
|
||||
/// </summary>
|
||||
/// <param name="inputfile">The file to encrypt</param>
|
||||
/// <param name="outputfile">The encrypted file</param>
|
||||
void Encrypt(string inputfile, string outputfile);
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts the contents of the input stream, and writes the result to the output stream.
|
||||
/// </summary>
|
||||
/// <param name="input">The stream to encrypt</param>
|
||||
/// <param name="output">The encrypted stream </param>
|
||||
void Encrypt(Stream input, Stream output);
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts the contents of the input file and saves the result as the outputfile
|
||||
/// </summary>
|
||||
/// <param name="inputfile">The file to decrypt</param>
|
||||
/// <param name="outputfile">The decrypted output file</param>
|
||||
void Decrypt(string inputfile, string outputfile);
|
||||
|
||||
/// <summary>
|
||||
/// Dencrypts the contents of the input stream, and writes the result to the output stream.
|
||||
/// </summary>
|
||||
/// <param name="input">The stream to decrypt</param>
|
||||
/// <param name="output">The decrypted stream</param>
|
||||
void Decrypt(Stream input, Stream output);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("Duplicati.Encryption")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("HexaD")]
|
||||
[assembly: AssemblyProduct("Duplicati.Encryption")]
|
||||
[assembly: AssemblyCopyright("Copyright © HexaD 2008")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("ea360f7d-b721-452e-8a7d-60da8ad1094f")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -174,10 +174,8 @@ namespace Duplicati.Main.RSync
|
||||
string s = m_unproccesed[next];
|
||||
m_unproccesed.RemoveAt(next);
|
||||
|
||||
//TODO: Add the delta to zip, don't use temp file
|
||||
if (ProccessDiff(s, sigfile))
|
||||
totalSize = AddFileToCompression(s, c);
|
||||
|
||||
}
|
||||
|
||||
if (m_unproccesed.Count == 0)
|
||||
|
||||
Reference in New Issue
Block a user