Sylloge
A C# helper library
code/Encryption/BinaryStream.cs
Go to the documentation of this file.
00001 using System;
00002 using System.Collections.Generic;
00003 using System.Linq;
00004 using System.Security.Cryptography;
00005 using System.Text;
00006 
00007 namespace Sylloge.Encryption
00008 {
00009     public class BinaryStream : IDisposable
00010     {
00015         public enum StreamType
00016         {
00020             Encrypt,
00024             Decrypt
00025         }
00026 
00030         public enum AlgorithmType
00031         {
00035             AES,
00039             AES_Rijndael,
00043             TripleDES
00044         }
00045 
00046         private System.Security.Cryptography.SymmetricAlgorithm m_algo;
00047         private System.Security.Cryptography.CryptoStream m_crypto;
00048         private System.IO.MemoryStream m_stream;
00049 
00053         public StreamType Type { get; protected set; }
00057         public AlgorithmType Algorithm { get; protected set; }
00058 
00059         public BinaryStream(AlgorithmType algo, StreamType type, int blockSize, int keySize, string pass, byte[] salt)
00060         {
00061             if (salt == null || salt.Length == 0) { throw new System.ArgumentException("Salt cannot be null or 0 length"); }
00062             PasswordDeriveBytes pdb = new System.Security.Cryptography.PasswordDeriveBytes(pass, salt);
00063             byte[] val = pdb.GetBytes(32);
00064             this.Initialize(algo, type, blockSize, keySize, val, val, CryptoStreamMode.Write);
00065         }
00066 
00067         public BinaryStream(AlgorithmType algo, StreamType type, int blockSize, int keySize, string pass, byte[] salt, CryptoStreamMode mode)
00068         {
00069             if (salt == null || salt.Length == 0) { throw new System.ArgumentException("Salt cannot be null or 0 length"); }
00070             PasswordDeriveBytes pdb = new System.Security.Cryptography.PasswordDeriveBytes(pass, salt);
00071             byte[] val = pdb.GetBytes(32);
00072             this.Initialize(algo, type, blockSize, keySize, val, val, mode);
00073         }
00074 
00075         public BinaryStream(AlgorithmType algo, StreamType type, int blockSize, int keySize, byte[] key, byte[] iv)
00076         {
00077             this.Initialize(algo, type, blockSize, keySize, key, iv, CryptoStreamMode.Write);
00078         }
00079 
00080         public BinaryStream(AlgorithmType algo, StreamType type, int blockSize, int keySize, byte[] key, byte[] iv, CryptoStreamMode mode)
00081         {
00082             this.Initialize(algo, type, blockSize, keySize, key, iv, mode);
00083         }
00084         
00088         public bool CanRead
00089         {
00090             get { return this.m_crypto.CanRead; }
00091         }
00092         
00096         public bool CanWrite
00097         {
00098             get { return this.m_crypto.CanWrite; }
00099         }
00100 
00101         public void Close()
00102         {
00103             this.m_crypto.Close();
00104             // TODO: implement the rest of these methods for the stream .. no easy way
00105             // to achieve this since we're dealing with 2 streams
00106             //this.m_crypto.BeginRead(
00107         }
00108 
00112         public void Dispose()
00113         {
00114             this.m_crypto.Close();
00115             this.m_crypto = null;
00116             this.m_stream = null;
00117             this.m_algo = null;
00118         }
00119 
00123         public void Flush()
00124         {
00125             this.m_crypto.Flush();
00126         }
00127 
00137         public int Read(byte[] buffer, int offset, int count)
00138         {
00139             return this.m_crypto.Read(buffer, offset, count);
00140         }
00141 
00147         public int ReadByte()
00148         {
00149             return this.m_crypto.ReadByte();
00150         }
00151 
00156         public void WriteByte(byte value)
00157         {
00158             this.m_crypto.WriteByte(value);
00159         }
00160 
00166         public void Write(byte[] buffer)
00167         {
00168             if (buffer == null || buffer.Length == 0) { throw new System.FormatException("Data cannot be null or 0 length"); }
00169             this.Write(buffer, 0, buffer.Length);
00170         }
00171 
00179         public void Write(byte[] buffer, int offset, int count)
00180         {
00181             if (buffer == null || buffer.Length == 0) { throw new System.FormatException("Data cannot be null or 0 length"); }
00182             if (offset > buffer.Length) { throw new System.FormatException("Offset must be less than length"); }
00183             if (count > (buffer.Length - offset)) { throw new System.FormatException("Count must be less than byte count and remaining bytes from offset"); }
00184             this.m_crypto.Write(buffer, offset, count);
00185         }
00186 
00191         public byte[] ToArray()
00192         {
00193             return this.m_stream.ToArray();
00194         }
00195 
00196         private void Initialize(AlgorithmType algo, StreamType type, int blockSize, int keySize, byte[] key, byte[] iv, CryptoStreamMode mode)
00197         {
00198             if (key == null || key.Length == 0) { throw new System.FormatException("Key cannot be null or 0 length"); }
00199             if (iv == null || iv.Length == 0) { throw new System.FormatException("Initialization vector cannot be null or 0 length"); }
00200             this.Type = type;
00201             this.m_stream = new System.IO.MemoryStream();
00202             this.InitializeAlgorithm(algo, blockSize, keySize, key, iv);
00203             this.m_crypto = new CryptoStream(this.m_stream, (type == StreamType.Encrypt ? this.m_algo.CreateEncryptor() : this.m_algo.CreateDecryptor()), mode);
00204         }
00205 
00206         private void InitializeAlgorithm(AlgorithmType algo, int blockSize, int keySize, byte[] key, byte[] iv)
00207         {
00208             this.Algorithm = algo;
00209             switch (this.Algorithm) {
00210                 case AlgorithmType.AES: this.m_algo = System.Security.Cryptography.Aes.Create(); break;
00211                 case AlgorithmType.AES_Rijndael: this.m_algo = System.Security.Cryptography.Rijndael.Create(); break;
00212                 case AlgorithmType.TripleDES: this.m_algo = System.Security.Cryptography.TripleDES.Create(); break;
00213                 default: throw new System.ArgumentException("Algorithm type unsupported");
00214             }
00215             bool foundbs = false;
00216             foreach (System.Security.Cryptography.KeySizes ks in this.m_algo.LegalBlockSizes) {
00217                 if (blockSize <= ks.MaxSize && blockSize >= ks.MinSize) {
00218                     foundbs = true; break;
00219                 }
00220             }
00221             if (!foundbs) { throw new System.Security.Cryptography.CryptographicException("Illegal block size specified"); }
00222             if (!this.m_algo.ValidKeySize(keySize)) { throw new System.Security.Cryptography.CryptographicException("Illegal key size specified"); }
00223 
00224             this.m_algo.BlockSize = blockSize;
00225             this.m_algo.KeySize = keySize;
00226             this.m_algo.Key = key;
00227             this.m_algo.IV = iv;
00228         }
00229     }
00230 }
 All Classes Namespaces Files Functions Variables Enumerations Properties Events