Created
September 9, 2014 02:37
-
-
Save patsissons/a80fef566a4d55988f14 to your computer and use it in GitHub Desktop.
Extension methods to easily and efficiently convert a file to a compressed, password encrypted byte array (and back)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// I had a requirement to read a file from local storage, compress the content, the encrypt the data with a password. | |
// There are many ways to do this, but I wanted to do it the most efficient and elegant way possible. | |
// This method takes advantage of using Streams (which pipe data between streams), which gives us a clean and efficient solution. | |
// I am using all the generally accepted best practices to accomplish the task at hand. | |
// I have implemented the solution as an extension method to simplify usage. | |
public static partial class ExtensionMethods | |
{ | |
#region File Encryption / Decryption | |
// WARN: this is an empty salt, create your own random salt using | |
// System.Security.Cryptography.RNGCryptoServiceProvider.GetNonZeroBytes(byte[]) | |
private static readonly byte[] Salt = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | |
public static byte[] GetEncryptedContent(this FileInfo source, string password, byte[] salt = null, int iterations = 1000) | |
{ | |
byte[] buffer = null; | |
if (source != null) | |
{ | |
source.Refresh(); | |
if (source.Exists) | |
{ | |
using (var ms = new MemoryStream()) | |
using (var crypt = Rijndael.Create()) | |
using (var pdb = new Rfc2898DeriveBytes(password, salt ?? DefaultSalt, iterations)) | |
{ | |
crypt.Key = pdb.GetBytes(32); | |
crypt.IV = pdb.GetBytes(16); | |
using (var crypts = new CryptoStream(ms, crypt.CreateEncryptor(), CryptoStreamMode.Write)) | |
using (var gzip = new GZipStream(crypts, CompressionLevel.Optimal)) | |
using (var fs = source.OpenRead()) | |
{ | |
fs.CopyTo(gzip); | |
} | |
buffer = ms.ToArray(); | |
} | |
} | |
} | |
return buffer; | |
} | |
public static void SaveDecryptedContent(this FileInfo source, byte[] buffer, string password, byte[] salt = null, int iterations = 1000) | |
{ | |
if (source != null && buffer != null && buffer.Length > 0) | |
{ | |
using (var ms = new MemoryStream(buffer)) | |
using (var crypt = Rijndael.Create()) | |
using (var pdb = new Rfc2898DeriveBytes(password, salt ?? DefaultSalt, iterations)) | |
{ | |
crypt.Key = pdb.GetBytes(32); | |
crypt.IV = pdb.GetBytes(16); | |
using (var crypts = new CryptoStream(ms, crypt.CreateDecryptor(), CryptoStreamMode.Read)) | |
using (var gzip = new GZipStream(crypts, CompressionMode.Decompress)) | |
using (var fs = source.OpenWrite()) | |
{ | |
gzip.CopyTo(fs); | |
// set the end of the file at the current position (trim off what remains in the buffer from being written to the file) | |
fs.SetLength(fs.Position); | |
} | |
} | |
} | |
} | |
#endregion | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment