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
79 public virtual byte[] IV {
\r
81 if (this.IVValue == null)
\r
84 return this.IVValue;
\r
88 throw new ArgumentNullException("tried setting initial vector to null");
\r
90 // FIXME: dont know if to compare with block or key size
\r
91 if (value.Length != this.KeySizeValue)
\r
92 throw new CryptographicException("tried setting initial vector with illegal size");
\r
94 this.IVValue = new byte [value.Length];
\r
95 System.Array.Copy (value, 0, this.IVValue, 0, value.Length);
\r
100 /// Gets or sets the actual key
\r
102 public virtual byte[] Key {
\r
104 if (this.KeyValue == null)
\r
107 return this.KeyValue;
\r
111 throw new ArgumentNullException("tried setting key to null");
\r
113 if (!IsLegalKeySize(this.LegalKeySizesValue, value.Length))
\r
114 throw new CryptographicException("key size not supported by algorithm");
\r
116 this.KeySizeValue = value.Length;
\r
117 this.KeyValue = new byte [this.KeySizeValue];
\r
118 System.Array.Copy (value, 0, this.KeyValue, 0, this.KeySizeValue);
\r
123 /// Gets or sets the actual key size
\r
125 public virtual int KeySize {
\r
127 return this.KeySizeValue;
\r
130 if (!IsLegalKeySize(this.LegalKeySizesValue, value))
\r
131 throw new CryptographicException("key size not supported by algorithm");
\r
133 this.KeyValue = null;
\r
134 this.KeySizeValue = value;
\r
139 /// Gets all legal block sizes
\r
141 public virtual KeySizes[] LegalBlockSizes {
\r
143 return this.LegalBlockSizesValue;
\r
148 /// Gets all legal key sizes
\r
150 public virtual KeySizes[] LegalKeySizes {
\r
152 return this.LegalKeySizesValue;
\r
157 /// Gets or sets the actual cipher mode
\r
159 public virtual CipherMode Mode {
\r
161 return this.ModeValue;
\r
164 if (Enum.IsDefined(ModeValue.GetType(), value))
\r
165 this.ModeValue = value;
\r
167 throw new CryptographicException("padding mode not available");
\r
172 /// Gets or sets the actual padding
\r
174 public virtual PaddingMode Padding {
\r
176 return this.PaddingValue;
\r
179 if (Enum.IsDefined(PaddingValue.GetType(), value))
\r
180 this.PaddingValue = value;
\r
182 throw new CryptographicException("padding mode not available");
\r
187 /// Gets an Decryptor transform object to work with a CryptoStream
\r
189 public virtual ICryptoTransform CreateDecryptor() {
\r
190 return CreateDecryptor(Key, IV);
\r
194 /// Gets an Decryptor transform object to work with a CryptoStream
\r
196 public abstract ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV);
\r
199 /// Gets an Encryptor transform object to work with a CryptoStream
\r
201 public virtual ICryptoTransform CreateEncryptor() {
\r
202 return CreateEncryptor(Key, IV);
\r
206 /// Gets an Encryptor transform object to work with a CryptoStream
\r
208 public abstract ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV);
\r
211 /// used to generate an inital vector if none is specified
\r
213 public abstract void GenerateIV();
\r
216 /// used to generate a random key if none is specified
\r
218 public abstract void GenerateKey();
\r
220 internal bool IsLegalKeySize(KeySizes[] LegalKeys, int Size) {
\r
221 foreach (KeySizes LegalKeySize in LegalKeys) {
\r
222 for (int i=LegalKeySize.MinSize; i<=LegalKeySize.MaxSize; i+=LegalKeySize.SkipSize) {
\r
231 /// Checks wether the given keyLength is valid for the current algorithm
\r
233 /// <param name="bitLength">the given keyLength</param>
\r
234 public bool ValidKeySize(int bitLength) {
\r
235 return IsLegalKeySize(LegalKeySizesValue, bitLength);
\r
239 /// Creates the default implementation of the default symmetric algorithm (RC2).
\r
241 public static SymmetricAlgorithm Create () {
\r
242 return Rijndael.Create();
\r
246 /// Creates a specific implementation of the given symmetric algorithm.
\r
248 /// <param name="algName">the given algorithm</param>
\r
250 public static SymmetricAlgorithm Create (string algName) {
\r
251 // TODO: Use Reflection to create a new algorithm instance
\r