2 // System.Security.Cryptography SymmetricAlgorithm Class implementation
\r
5 // Thomas Neidhart (tome@sbox.tugraz.at)
\r
10 namespace System.Security.Cryptography {
\r
13 /// Abstract base class for all cryptographic symmetric algorithms.
\r
14 /// Available algorithms include:
\r
15 /// DES, RC2, Rijndael, TripleDES
\r
17 public abstract class SymmetricAlgorithm {
\r
18 protected int BlockSizeValue; // The block size of the cryptographic operation in bits.
\r
19 protected int FeedbackSizeValue; // The feedback size of the cryptographic operation in bits.
\r
20 protected byte[] IVValue; // The initialization vector ( IV) for the symmetric algorithm.
\r
21 protected int KeySizeValue; // The size of the secret key used by the symmetric algorithm in bits.
\r
22 protected byte[] KeyValue; // The secret key for the symmetric algorithm.
\r
23 protected KeySizes[] LegalBlockSizesValue; // Specifies the block sizes that are supported by the symmetric algorithm.
\r
24 protected KeySizes[] LegalKeySizesValue; // Specifies the key sizes that are supported by the symmetric algorithm.
\r
25 protected CipherMode ModeValue; // Represents the cipher mode used in the symmetric algorithm.
\r
26 protected PaddingMode PaddingValue; // Represents the padding mode used in the symmetric algorithm.
\r
29 /// Called from constructor of derived class.
\r
31 public SymmetricAlgorithm () {
\r
32 throw new CryptographicException();
\r
36 /// Called from constructor of derived class.
\r
38 ~SymmetricAlgorithm () {
\r
39 if (KeyValue != null) {
\r
40 Array.Clear(KeyValue, 0, KeyValue.Length);
\r
46 /// Gets or sets the actual BlockSize
\r
48 public virtual int BlockSize {
\r
50 return this.BlockSizeValue;
\r
53 if (IsLegalKeySize(this.LegalBlockSizesValue, value))
\r
54 this.BlockSizeValue = value;
\r
56 throw new CryptographicException("block size not supported by algorithm");
\r
61 /// Gets or sets the actual FeedbackSize
\r
63 public virtual int FeedbackSize {
\r
65 return this.FeedbackSizeValue;
\r
68 if (value > this.BlockSizeValue)
\r
69 throw new CryptographicException("feedback size larger than block size");
\r
71 this.FeedbackSizeValue = value;
\r
76 /// Gets or sets the actual Initial Vector
\r
78 public virtual byte[] IV {
\r
80 if (this.IVValue == null)
\r
83 return this.IVValue;
\r
87 throw new ArgumentNullException("tried setting initial vector to null");
\r
89 // FIXME: dont know if to compare with block or key size
\r
90 if (value.Length != this.KeySizeValue)
\r
91 throw new CryptographicException("tried setting initial vector with illegal size");
\r
93 this.IVValue = new byte [value.Length];
\r
94 System.Array.Copy (value, 0, this.IVValue, 0, value.Length);
\r
99 /// Gets or sets the actual key
\r
101 public virtual byte[] Key {
\r
103 if (this.KeyValue == null)
\r
106 return this.KeyValue;
\r
110 throw new ArgumentNullException("tried setting key to null");
\r
112 if (!IsLegalKeySize(this.LegalKeySizesValue, value.Length))
\r
113 throw new CryptographicException("key size not supported by algorithm");
\r
115 this.KeySizeValue = value.Length;
\r
116 this.KeyValue = new byte [this.KeySizeValue];
\r
117 System.Array.Copy (value, 0, this.KeyValue, 0, this.KeySizeValue);
\r
122 /// Gets or sets the actual key size
\r
124 public virtual int KeySize {
\r
126 return this.KeySizeValue;
\r
129 if (!IsLegalKeySize(this.LegalKeySizesValue, value))
\r
130 throw new CryptographicException("key size not supported by algorithm");
\r
132 this.KeyValue = null;
\r
133 this.KeySizeValue = value;
\r
138 /// Gets all legal block sizes
\r
140 public virtual KeySizes[] LegalBlockSizes {
\r
142 return this.LegalBlockSizesValue;
\r
147 /// Gets all legal key sizes
\r
149 public virtual KeySizes[] LegalKeySizes {
\r
151 return this.LegalKeySizesValue;
\r
156 /// Gets or sets the actual cipher mode
\r
158 public virtual CipherMode Mode {
\r
160 return this.ModeValue;
\r
163 if (Enum.IsDefined(ModeValue.GetType(), value))
\r
164 this.ModeValue = value;
\r
166 throw new CryptographicException("padding mode not available");
\r
171 /// Gets or sets the actual padding
\r
173 public virtual PaddingMode Padding {
\r
175 return this.PaddingValue;
\r
178 if (Enum.IsDefined(PaddingValue.GetType(), value))
\r
179 this.PaddingValue = value;
\r
181 throw new CryptographicException("padding mode not available");
\r
186 /// Gets an Decryptor transform object to work with a CryptoStream
\r
188 public virtual ICryptoTransform CreateDecryptor() {
\r
189 return CreateDecryptor(Key, IV);
\r
193 /// Gets an Decryptor transform object to work with a CryptoStream
\r
195 public abstract ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV);
\r
198 /// Gets an Encryptor transform object to work with a CryptoStream
\r
200 public virtual ICryptoTransform CreateEncryptor() {
\r
201 return CreateEncryptor(Key, IV);
\r
205 /// Gets an Encryptor transform object to work with a CryptoStream
\r
207 public abstract ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV);
\r
210 /// used to generate an inital vector if none is specified
\r
212 public abstract void GenerateIV();
\r
215 /// used to generate a random key if none is specified
\r
217 public abstract void GenerateKey();
\r
219 internal bool IsLegalKeySize(KeySizes[] LegalKeys, int Size) {
\r
220 foreach (KeySizes LegalKeySize in LegalKeys) {
\r
221 for (int i=LegalKeySize.MinSize; i<=LegalKeySize.MaxSize; i+=LegalKeySize.SkipSize) {
\r
230 /// Checks wether the given keyLength is valid for the current algorithm
\r
232 /// <param name="bitLength">the given keyLength</param>
\r
233 public bool ValidKeySize(int bitLength) {
\r
234 return IsLegalKeySize(LegalKeySizesValue, bitLength);
\r
238 /// Creates the default implementation of the default symmetric algorithm (RC2).
\r
240 public static SymmetricAlgorithm Create () {
\r
241 return Rijndael.Create();
\r
245 /// Creates a specific implementation of the given symmetric algorithm.
\r
247 /// <param name="algName">the given algorithm</param>
\r
248 public static SymmetricAlgorithm Create (string algName) {
\r
249 // TODO: Use Reflection to create a new algorithm instance
\r