// // System.Security.Cryptography SymmetricAlgorithm Class implementation // // Authors: // Thomas Neidhart (tome@sbox.tugraz.at) // Sebastien Pouliot (spouliot@motus.com) // // Portions (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com) // using System; using Mono.Security.Cryptography; namespace System.Security.Cryptography { /// /// Abstract base class for all cryptographic symmetric algorithms. /// Available algorithms include: /// DES, RC2, Rijndael, TripleDES /// public abstract class SymmetricAlgorithm : IDisposable { protected int BlockSizeValue; // The block size of the cryptographic operation in bits. protected int FeedbackSizeValue; // The feedback size of the cryptographic operation in bits. protected byte[] IVValue; // The initialization vector ( IV) for the symmetric algorithm. protected int KeySizeValue; // The size of the secret key used by the symmetric algorithm in bits. protected byte[] KeyValue; // The secret key for the symmetric algorithm. protected KeySizes[] LegalBlockSizesValue; // Specifies the block sizes that are supported by the symmetric algorithm. protected KeySizes[] LegalKeySizesValue; // Specifies the key sizes that are supported by the symmetric algorithm. protected CipherMode ModeValue; // Represents the cipher mode used in the symmetric algorithm. protected PaddingMode PaddingValue; // Represents the padding mode used in the symmetric algorithm. private bool m_disposed; /// /// Called from constructor of derived class. /// public SymmetricAlgorithm () { ModeValue = CipherMode.CBC; PaddingValue = PaddingMode.PKCS7; m_disposed = false; } /// /// Called from constructor of derived class. /// ~SymmetricAlgorithm () { Dispose (false); } public void Clear() { Dispose (true); } void IDisposable.Dispose () { Dispose (true); GC.SuppressFinalize (this); // Finalization is now unnecessary } protected virtual void Dispose (bool disposing) { if (!m_disposed) { // always zeroize keys if (KeyValue != null) { // Zeroize the secret key and free Array.Clear (KeyValue, 0, KeyValue.Length); KeyValue = null; } // dispose unmanaged managed objects if (disposing) { // dispose managed objects } m_disposed = true; } } /// /// Gets or sets the actual BlockSize /// public virtual int BlockSize { get { return this.BlockSizeValue; } set { if (KeySizes.IsLegalKeySize (this.LegalBlockSizesValue, value)) this.BlockSizeValue = value; else throw new CryptographicException("block size not supported by algorithm"); } } /// /// Gets or sets the actual FeedbackSize /// public virtual int FeedbackSize { get { return this.FeedbackSizeValue; } set { if (value > this.BlockSizeValue) throw new CryptographicException("feedback size larger than block size"); else this.FeedbackSizeValue = value; } } /// /// Gets or sets the actual Initial Vector /// public virtual byte[] IV { get { if (this.IVValue == null) GenerateIV(); return this.IVValue; } set { if (value == null) throw new ArgumentNullException ("tried setting initial vector to null"); if (value.Length * 8 != this.BlockSizeValue) throw new CryptographicException ("IV length must match block size"); this.IVValue = new byte [value.Length]; Array.Copy (value, 0, this.IVValue, 0, value.Length); } } /// /// Gets or sets the actual key /// public virtual byte[] Key { get { if (this.KeyValue == null) GenerateKey(); return this.KeyValue; } set { if (value == null) throw new ArgumentNullException ("tried setting key to null"); if (!KeySizes.IsLegalKeySize (this.LegalKeySizesValue, value.Length * 8)) throw new CryptographicException ("key size not supported by algorithm"); this.KeySizeValue = value.Length * 8; this.KeyValue = new byte [value.Length]; Array.Copy (value, 0, this.KeyValue, 0, value.Length); } } /// /// Gets or sets the actual key size in bits /// public virtual int KeySize { get { return this.KeySizeValue; } set { if (!KeySizes.IsLegalKeySize (this.LegalKeySizesValue, value)) throw new CryptographicException ("key size not supported by algorithm"); this.KeyValue = null; this.KeySizeValue = value; } } /// /// Gets all legal block sizes /// public virtual KeySizes[] LegalBlockSizes { get { return this.LegalBlockSizesValue; } } /// /// Gets all legal key sizes /// public virtual KeySizes[] LegalKeySizes { get { return this.LegalKeySizesValue; } } /// /// Gets or sets the actual cipher mode /// public virtual CipherMode Mode { get { return this.ModeValue; } set { if (Enum.IsDefined( ModeValue.GetType (), value)) this.ModeValue = value; else throw new CryptographicException ("padding mode not available"); } } /// /// Gets or sets the actual padding /// public virtual PaddingMode Padding { get { return this.PaddingValue; } set { if (Enum.IsDefined (PaddingValue.GetType (), value)) this.PaddingValue = value; else throw new CryptographicException ("padding mode not available"); } } /// /// Gets an Decryptor transform object to work with a CryptoStream /// public virtual ICryptoTransform CreateDecryptor () { return CreateDecryptor (Key, IV); } /// /// Gets an Decryptor transform object to work with a CryptoStream /// public abstract ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV); /// /// Gets an Encryptor transform object to work with a CryptoStream /// public virtual ICryptoTransform CreateEncryptor() { return CreateEncryptor (Key, IV); } /// /// Gets an Encryptor transform object to work with a CryptoStream /// public abstract ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV); /// /// used to generate an inital vector if none is specified /// public abstract void GenerateIV (); /// /// used to generate a random key if none is specified /// public abstract void GenerateKey (); /// /// Checks wether the given keyLength is valid for the current algorithm /// /// the given keyLength public bool ValidKeySize (int bitLength) { return KeySizes.IsLegalKeySize (LegalKeySizesValue, bitLength); } /// /// Creates the default implementation of the default symmetric algorithm (Rijndael). /// // LAMESPEC: Default is Rijndael - not TripleDES public static SymmetricAlgorithm Create () { return Create ("System.Security.Cryptography.SymmetricAlgorithm"); } /// /// Creates a specific implementation of the given symmetric algorithm. /// /// Specifies which derived class to create public static SymmetricAlgorithm Create (string algName) { return (SymmetricAlgorithm) CryptoConfig.CreateFromName (algName); } } }