//
// 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 ("IV");
if ((value.Length << 3) > this.BlockSizeValue)
throw new CryptographicException ("IV length cannot be larger than block size");
this.IVValue = (byte[]) value.Clone ();
}
}
///
/// 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 ("Key");
int length = (value.Length << 3);
if (!KeySizes.IsLegalKeySize (this.LegalKeySizesValue, length))
throw new CryptographicException ("key size not supported by algorithm");
this.KeySizeValue = length;
this.KeyValue = (byte[]) value.Clone ();
}
}
///
/// 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);
}
}
}