Home > General > Encrypting files

Encrypting files

I have several files I need to backup to the cloud. I looked at automated backup solutions like Mozy, CrashPlan, etc…, but they were expensive compared to storage solutions like Amazon S3, Azure Storage, and others. So I figure that I can just encrypt the files myself and upload it to one of those services. I wrote the code below to encrypt my files:

void Main()
{
	string pass = "$ecret p@ssword";
	 
	string source = @"C:\file.dat";
	string encryptedDestination = @"C:\file.encrypted";
	string decryptedDestination = @"C:\file.decrypted.dat";
	
	byte[] salt = EncryptFile(pass, source, encryptedDestination);
	DecryptFile(pass, salt, encryptedDestination, decryptedDestination);
			 
	Console.WriteLine ("Done");
}

byte[] EncryptFile(string password, string source, string destination)
{	
	if (!File.Exists(source))
		throw new ArgumentException("Source does not exist.", "source");
	
	if (File.Exists(destination))
		throw new ArgumentException("Destination already exist.", "destination");
		
	byte[] IV;
	
	using (var provider = new RijndaelManaged())
	using (var passwordGen = new Rfc2898DeriveBytes(password, provider.IV))
	{
		provider.Key = passwordGen.GetBytes(provider.KeySize / 8);
		IV = provider.IV;
			
		using (var encrypt = provider.CreateEncryptor())
		using (var destinationStream = File.Create(destination))
		using (var cryptoStream = new CryptoStream(destinationStream, encrypt, CryptoStreamMode.Write))
		using (var sourceStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.Read))
		{
			sourceStream.CopyTo(cryptoStream);
		}
	}
	
	return IV;
}

void DecryptFile(string password, byte[] salt, string source, string destination)
{
	if (!File.Exists(source))
		throw new ArgumentException("Source does not exist.", "source");
	
	if (File.Exists(destination))
		throw new ArgumentException("Destination already exist.", "destination");
		
	using (var provider = new RijndaelManaged())
	using (var passwordGen = new Rfc2898DeriveBytes(password, salt))
	{
		provider.Key = passwordGen.GetBytes(provider.KeySize / 8);
		provider.IV = salt;
				
		using (var decrypt = provider.CreateDecryptor())
		using (var destinationStream = File.Create(destination))
		using (var cryptoStream = new CryptoStream(destinationStream, decrypt, CryptoStreamMode.Write))
		using (var sourceStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.Read))
		{
			sourceStream.CopyTo(cryptoStream);
		}
	}
}

Although the encryption code works, I still need to store the generated initialization vectors (IV) somewhere along with the encrypted files. That’s kind of a hassle. Instead, I can prepend the IV to the encrypted files. When I’m decrypting files, I can read the first 16 bytes and assume that’s the IV.

void EncryptFile(string password, string source, string destination)
{   
    if (!File.Exists(source))
        throw new ArgumentException("Source does not exist.", "source");
     
    if (File.Exists(destination))
        throw new ArgumentException("Destination already exist.", "destination");
     
    using (var provider = new RijndaelManaged())
    using (var passwordGen = new Rfc2898DeriveBytes(password, provider.IV))
    {
        provider.Key = passwordGen.GetBytes(provider.KeySize / 8);
                     
        using (var encrypt = provider.CreateEncryptor())
        using (var destinationStream = File.Create(destination))
		using (var cryptoStream = new CryptoStream(destinationStream, encrypt, CryptoStreamMode.Write))
		using (var sourceStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.Read))
		{
			destinationStream.Write(provider.IV, 0, provider.IV.Length);
			sourceStream.CopyTo(cryptoStream);
		}
    }
}
 
void DecryptFile(string password, string source, string destination)
{
    if (!File.Exists(source))
        throw new ArgumentException("Source does not exist.", "source");
     
    if (File.Exists(destination))
        throw new ArgumentException("Destination already exist.", "destination");
	
	byte[] salt = new byte[16];
	
	using (var sourceStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.Read))
	{
		sourceStream.Read(salt, 0, salt.Length);
	}
	
    using (var provider = new RijndaelManaged())
    using (var passwordGen = new Rfc2898DeriveBytes(password, salt))
    {
        provider.Key = passwordGen.GetBytes(provider.KeySize / 8);
        provider.IV = salt;
                 
        using (var decrypt = provider.CreateDecryptor())
        using (var destinationStream = File.Create(destination))
        using (var cryptoStream = new CryptoStream(destinationStream, decrypt, CryptoStreamMode.Write))
        using (var sourceStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.Read))
        {
			sourceStream.Seek(salt.Length, SeekOrigin.Begin);
            sourceStream.CopyTo(cryptoStream);
        }
    }
}
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: