![]() |
Sylloge
A C# helper library
|
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 }
1.7.4