Provides methods that process data in a Stream into another Stream. Can be used to provide features such as data compression or encryption
Inheritance Hierarchy
NetworkCommsDotNet.DPSBase DataProcessor
NetworkCommsDotNet.DPSBase DataPadder
NetworkCommsDotNet.DPSBase RijndaelPSKEncrypter
NetworkCommsDotNet.DPSBase.SevenZipLZMACompressor LZMACompressor
QuickLZCompressor QuickLZ
SharpZipLibCompressor SharpZipLibGzipCompressor
Namespace: NetworkCommsDotNet.DPSBase
Assembly: NetworkCommsDotNet (in NetworkCommsDotNet.dll) Version: 3.0.0.0 (3.0.0.0)
Syntax
Examples
// Copyright 2009-2014 Marc Fletcher, Matthew Dean // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. // // Non-GPL versions of this software can also be purchased. // Please see <http://www.networkcomms.net> for details. using System; using System.Collections.Generic; using System.Text; using System.IO; #if NETFX_CORE using Windows.Security.Cryptography.Core; using Windows.Storage.Streams; using Windows.Security.Cryptography; using System.Runtime.InteropServices.WindowsRuntime; #else using System.Security.Cryptography; using NetworkCommsDotNet.Tools; #endif #if ANDROID using PreserveAttribute = Android.Runtime.PreserveAttribute; #elif iOS using PreserveAttribute = MonoTouch.Foundation.PreserveAttribute; #endif namespace NetworkCommsDotNet.DPSBase { #if !FREETRIAL /// <summary> /// <see cref="DataProcessor"/> which encrypts/decrypts data using the Rijndael algorithm and a pre-shared password /// </summary> [DataSerializerProcessor(4)] [SecurityCriticalDataProcessor(true)] public class RijndaelPSKEncrypter : DataProcessor, IDisposable { private const string PasswordOption = "RijndaelPSKEncrypter_PASSWORD"; private static readonly byte[] SALT = new byte[] { 118, 100, 123, 136, 20, 242, 170, 227, 97, 168, 101, 177, 214, 211, 118, 137 }; #if WINDOWS_PHONE SymmetricAlgorithm encrypter = new AesManaged(); #elif !NETFX_CORE SymmetricAlgorithm encrypter = new RijndaelManaged(); #endif #if ANDROID || iOS [Preserve] #endif private RijndaelPSKEncrypter() { #if !NETFX_CORE encrypter.BlockSize = 128; #endif } /// <inheritdoc /> public override void ForwardProcessDataStream(System.IO.Stream inStream, System.IO.Stream outStream, Dictionary<string, string> options, out long writtenBytes) { if (options == null) throw new ArgumentNullException("options"); else if (!options.ContainsKey(PasswordOption)) throw new ArgumentException("Options must contain encryption key", "options"); if (outStream == null) throw new ArgumentNullException("outStream"); #if NETFX_CORE inStream.Seek(0, 0); outStream.Seek(0, 0); IBuffer pwBuffer = CryptographicBuffer.ConvertStringToBinary(options[PasswordOption], BinaryStringEncoding.Utf8); IBuffer saltBuffer = CryptographicBuffer.CreateFromByteArray(SALT); // Derive key material for password size 32 bytes for AES256 algorithm KeyDerivationAlgorithmProvider keyDerivationProvider = Windows.Security.Cryptography.Core.KeyDerivationAlgorithmProvider.OpenAlgorithm("PBKDF2_SHA1"); // using salt and 1000 iterations KeyDerivationParameters pbkdf2Parms = KeyDerivationParameters.BuildForPbkdf2(saltBuffer, 1000); // create a key based on original key and derivation parmaters CryptographicKey keyOriginal = keyDerivationProvider.CreateKey(pwBuffer); IBuffer keyMaterial = CryptographicEngine.DeriveKeyMaterial(keyOriginal, pbkdf2Parms, 32); CryptographicKey derivedPwKey = keyDerivationProvider.CreateKey(pwBuffer); // derive buffer to be used for encryption salt from derived password key IBuffer saltMaterial = CryptographicEngine.DeriveKeyMaterial(derivedPwKey, pbkdf2Parms, 16); // display the buffers - because KeyDerivationProvider always gets cleared after each use, they are very similar unforunately string keyMaterialString = CryptographicBuffer.EncodeToBase64String(keyMaterial); string saltMaterialString = CryptographicBuffer.EncodeToBase64String(saltMaterial); SymmetricKeyAlgorithmProvider symProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC_PKCS7"); // create symmetric key from derived password key CryptographicKey symmKey = symProvider.CreateSymmetricKey(keyMaterial); using (MemoryStream ms = new MemoryStream()) { inStream.CopyTo(ms); // encrypt data buffer using symmetric key and derived salt material IBuffer resultBuffer = CryptographicEngine.Encrypt(symmKey, WindowsRuntimeBufferExtensions.GetWindowsRuntimeBuffer(ms), saltMaterial); resultBuffer.AsStream().CopyTo(outStream); writtenBytes = outStream.Position; } #else Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(options[PasswordOption], SALT); var key = pdb.GetBytes(32); pdb.Reset(); var iv = pdb.GetBytes(16); using (var transform = encrypter.CreateEncryptor(key, iv)) { using (MemoryStream internalStream = new MemoryStream()) { using (CryptoStream csEncrypt = new CryptoStream(internalStream, transform, CryptoStreamMode.Write)) { StreamTools.Write(inStream, csEncrypt); inStream.Flush(); csEncrypt.FlushFinalBlock(); internalStream.Seek(0, 0); StreamTools.Write(internalStream, outStream); writtenBytes = outStream.Position; } } } #endif } /// <inheritdoc /> public override void ReverseProcessDataStream(System.IO.Stream inStream, System.IO.Stream outStream, Dictionary<string, string> options, out long writtenBytes) { if (options == null) throw new ArgumentNullException("options"); else if (!options.ContainsKey(PasswordOption)) throw new ArgumentException("Options must contain encryption key", "options"); if (outStream == null) throw new ArgumentNullException("outStream"); #if NETFX_CORE inStream.Seek(0, 0); outStream.Seek(0, 0); IBuffer pwBuffer = CryptographicBuffer.ConvertStringToBinary(options[PasswordOption], BinaryStringEncoding.Utf8); IBuffer saltBuffer = CryptographicBuffer.CreateFromByteArray(SALT); // Derive key material for password size 32 bytes for AES256 algorithm KeyDerivationAlgorithmProvider keyDerivationProvider = Windows.Security.Cryptography.Core.KeyDerivationAlgorithmProvider.OpenAlgorithm("PBKDF2_SHA1"); // using salt and 1000 iterations KeyDerivationParameters pbkdf2Parms = KeyDerivationParameters.BuildForPbkdf2(saltBuffer, 1000); // create a key based on original key and derivation parmaters CryptographicKey keyOriginal = keyDerivationProvider.CreateKey(pwBuffer); IBuffer keyMaterial = CryptographicEngine.DeriveKeyMaterial(keyOriginal, pbkdf2Parms, 32); CryptographicKey derivedPwKey = keyDerivationProvider.CreateKey(pwBuffer); // derive buffer to be used for encryption salt from derived password key IBuffer saltMaterial = CryptographicEngine.DeriveKeyMaterial(derivedPwKey, pbkdf2Parms, 16); // display the buffers - because KeyDerivationProvider always gets cleared after each use, they are very similar unforunately string keyMaterialString = CryptographicBuffer.EncodeToBase64String(keyMaterial); string saltMaterialString = CryptographicBuffer.EncodeToBase64String(saltMaterial); SymmetricKeyAlgorithmProvider symProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC_PKCS7"); // create symmetric key from derived password key CryptographicKey symmKey = symProvider.CreateSymmetricKey(keyMaterial); using (MemoryStream ms = new MemoryStream()) { inStream.CopyTo(ms); // encrypt data buffer using symmetric key and derived salt material IBuffer resultBuffer = CryptographicEngine.Decrypt(symmKey, WindowsRuntimeBufferExtensions.GetWindowsRuntimeBuffer(ms), saltMaterial); resultBuffer.AsStream().CopyTo(outStream); writtenBytes = outStream.Position; } #else Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(options[PasswordOption], SALT); var key = pdb.GetBytes(32); pdb.Reset(); var iv = pdb.GetBytes(16); using (var transform = encrypter.CreateDecryptor(key, iv)) { using (MemoryStream internalStream = new MemoryStream()) { using (CryptoStream csDecrypt = new CryptoStream(internalStream, transform, CryptoStreamMode.Write)) { StreamTools.Write(inStream, csDecrypt); inStream.Flush(); csDecrypt.FlushFinalBlock(); internalStream.Seek(0, 0); StreamTools.Write(internalStream, outStream); writtenBytes = outStream.Position; } } } #endif } /// <summary> /// Adds a password, using the correct key, to a Dictionary /// </summary> /// <param name="options">The Dictionary to add the option to</param> /// <param name="password">The password</param> public static void AddPasswordToOptions(Dictionary<string, string> options, string password) { if (options == null) throw new ArgumentNullException("options"); options[PasswordOption] = password; } /// <summary> /// Dispose of all resources. /// </summary> public void Dispose() { #if !NETFX_CORE if (encrypter != null) (encrypter as IDisposable).Dispose(); #endif } } #endif }
See Also