diff --git a/src/FileCache/FileCache.cs b/src/FileCache/FileCache.cs index 1212e09..cbff5f6 100644 --- a/src/FileCache/FileCache.cs +++ b/src/FileCache/FileCache.cs @@ -81,7 +81,11 @@ public enum PayloadMode /// /// Treat the paylad as raw bytes. A byte[] and readable streams are supported on add. /// - RawBytes + RawBytes, + /// + /// Treat the payload as a crypto serializable object. + /// + CryptoSerializable, } /// diff --git a/src/FileCache/FileCacheManager.cs b/src/FileCache/FileCacheManager.cs index b9515fd..c7c24f3 100644 --- a/src/FileCache/FileCacheManager.cs +++ b/src/FileCache/FileCacheManager.cs @@ -5,6 +5,7 @@ using System.Reflection; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; +using System.Security.Cryptography; using System.Text; using System.Threading; @@ -21,6 +22,7 @@ public abstract class FileCacheManager public string CacheSubFolder { get; set; } public string PolicySubFolder { get; set; } public SerializationBinder Binder { get; set; } + public string CryptoKey { get; set; } /// /// Used to determine how long the FileCache will wait for a file to become @@ -151,6 +153,9 @@ public virtual FileCachePayload ReadFile(FileCache.PayloadMode mode, string key, case FileCache.PayloadMode.RawBytes: payload.Payload = LoadRawPayloadData(cachePath); break; + case FileCache.PayloadMode.CryptoSerializable: + payload.Payload = DeserializeCrypto(cachePath); + break; default: throw new ArgumentOutOfRangeException(nameof(mode), mode, null); } @@ -222,6 +227,54 @@ protected virtual object Deserialize(string fileName, SerializationBinder object } return data; } + protected virtual object DeserializeCrypto(string fileName, SerializationBinder objectBinder = null) + { + object data = null; + if (File.Exists(fileName)) + { + AesCryptoServiceProvider aes = new AesCryptoServiceProvider(); + MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); + SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider(); + byte[] aeskey = sha256.ComputeHash(Encoding.UTF8.GetBytes(CryptoKey)); + byte[] aesiv = md5.ComputeHash(Encoding.UTF8.GetBytes(CryptoKey)); + aes.Key = aeskey; + aes.IV = aesiv; + + using (FileStream stream = GetStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + using (Stream cryptoStream = new CryptoStream(stream, aes.CreateDecryptor(), CryptoStreamMode.Read)) + { + BinaryFormatter formatter = new BinaryFormatter(); + + //AC: From http://spazzarama.com//2009/06/25/binary-deserialize-unable-to-find-assembly/ + // Needed to deserialize custom objects + if (objectBinder != null) + { + //take supplied binder over default binder + formatter.Binder = objectBinder; + } + else if (Binder != null) + { + formatter.Binder = Binder; + } + try + { + data = formatter.Deserialize(cryptoStream); + } + catch (SerializationException) + { + data = null; + } + finally + { + cryptoStream.Close(); + stream.Close(); + } + } + } + } + return data; + } /// /// This function serves to centralize file writes within this class @@ -276,6 +329,23 @@ public virtual long WriteFile(FileCache.PayloadMode mode, string key, FileCacheP case FileCache.PayloadMode.Filename: File.Copy((string)data.Payload, cachedItemPath, true); break; + case FileCache.PayloadMode.CryptoSerializable: + AesCryptoServiceProvider aes = new AesCryptoServiceProvider(); + MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); + SHA256CryptoServiceProvider sha256 = new SHA256CryptoServiceProvider(); + byte[] aeskey = sha256.ComputeHash(Encoding.UTF8.GetBytes(CryptoKey)); + byte[] aesiv = md5.ComputeHash(Encoding.UTF8.GetBytes(CryptoKey)); + aes.Key = aeskey; + aes.IV = aesiv; + using (FileStream stream = GetStream(cachedItemPath, FileMode.Create, FileAccess.Write, FileShare.None)) + { + using (CryptoStream cryptoStream = new CryptoStream(stream, aes.CreateEncryptor(), CryptoStreamMode.Write)) + { + BinaryFormatter formatter = new BinaryFormatter(); + formatter.Serialize(cryptoStream, data.Payload); + } + } + break; } //adjust cache size (while we have the file to ourselves)