2002-06-21 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / corlib / System.Security.Cryptography / SymmetricAlgorithm.cs
1 //\r
2 // System.Security.Cryptography SymmetricAlgorithm Class implementation\r
3 //\r
4 // Authors:\r
5 //   Thomas Neidhart (tome@sbox.tugraz.at)\r
6 //\r
7 \r
8 using System;\r
9 \r
10 namespace System.Security.Cryptography {\r
11         \r
12         /// <summary>\r
13         /// Abstract base class for all cryptographic symmetric algorithms.\r
14         /// Available algorithms include:\r
15         /// DES, RC2, Rijndael, TripleDES\r
16         /// </summary>\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
27 \r
28                 /// <summary>\r
29                 /// Called from constructor of derived class.\r
30                 /// </summary>\r
31                 public SymmetricAlgorithm () {\r
32                   throw new CryptographicException();\r
33                 }\r
34                 \r
35                 /// <summary>\r
36                 /// Called from constructor of derived class.\r
37                 /// </summary>\r
38                 ~SymmetricAlgorithm () {\r
39                         if (KeyValue != null) {\r
40                                 Array.Clear(KeyValue, 0, KeyValue.Length);\r
41                                 KeyValue = null;\r
42                         }\r
43                 }\r
44 \r
45                 /// <summary>\r
46                 /// Gets or sets the actual BlockSize\r
47                 /// </summary>\r
48                 public virtual int BlockSize {\r
49                         get {\r
50                                 return this.BlockSizeValue;\r
51                         }\r
52                         set {\r
53                                 if (IsLegalKeySize(this.LegalBlockSizesValue, value))\r
54                                         this.BlockSizeValue = value;\r
55                                 else\r
56                                         throw new CryptographicException("block size not supported by algorithm");\r
57                         }\r
58                 }\r
59 \r
60                 /// <summary>\r
61                 /// Gets or sets the actual FeedbackSize\r
62                 /// </summary>\r
63                 public virtual int FeedbackSize {\r
64                         get {\r
65                                 return this.FeedbackSizeValue;\r
66                         }\r
67                         set {\r
68                                 if (value > this.BlockSizeValue)\r
69                                         throw new CryptographicException("feedback size larger than block size");\r
70                                 else\r
71                                         this.FeedbackSizeValue = value;\r
72                         }\r
73                 }\r
74                 \r
75                 /// <summary>\r
76                 /// Gets or sets the actual Initial Vector\r
77                 /// </summary>\r
78                 [MonoTODO]\r
79                 public virtual byte[] IV {\r
80                         get {\r
81                                 if (this.IVValue == null)\r
82                                         GenerateIV();\r
83 \r
84                                 return this.IVValue;\r
85                         }\r
86                         set {\r
87                                 if (value == null)\r
88                                         throw new ArgumentNullException("tried setting initial vector to null");\r
89                                         \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
93                                 \r
94                                 this.IVValue = new byte [value.Length];\r
95                                 System.Array.Copy (value, 0, this.IVValue, 0, value.Length);\r
96                         }\r
97                 }\r
98 \r
99                 /// <summary>\r
100                 /// Gets or sets the actual key\r
101                 /// </summary>\r
102                 public virtual byte[] Key {\r
103                         get {\r
104                                 if (this.KeyValue == null)\r
105                                         GenerateKey();\r
106 \r
107                                 return this.KeyValue;\r
108                         }\r
109                         set {\r
110                                 if (value == null)\r
111                                         throw new ArgumentNullException("tried setting key to null");\r
112 \r
113                                 if (!IsLegalKeySize(this.LegalKeySizesValue, value.Length))\r
114                                         throw new CryptographicException("key size not supported by algorithm");\r
115 \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
119                         }\r
120                 }\r
121                 \r
122                 /// <summary>\r
123                 /// Gets or sets the actual key size\r
124                 /// </summary>\r
125                 public virtual int KeySize {\r
126                         get {\r
127                                 return this.KeySizeValue;\r
128                         }\r
129                         set {\r
130                                 if (!IsLegalKeySize(this.LegalKeySizesValue, value))\r
131                                         throw new CryptographicException("key size not supported by algorithm");\r
132                                 \r
133                                 this.KeyValue = null;\r
134                                 this.KeySizeValue = value;\r
135                         }\r
136                 }\r
137 \r
138                 /// <summary>\r
139                 /// Gets all legal block sizes\r
140                 /// </summary>\r
141                 public virtual KeySizes[] LegalBlockSizes {\r
142                         get {\r
143                                 return this.LegalBlockSizesValue;\r
144                         }\r
145                 }\r
146 \r
147                 /// <summary>\r
148                 /// Gets all legal key sizes\r
149                 /// </summary>\r
150                 public virtual KeySizes[] LegalKeySizes {\r
151                         get {\r
152                                 return this.LegalKeySizesValue;\r
153                         }\r
154                 }\r
155 \r
156                 /// <summary>\r
157                 /// Gets or sets the actual cipher mode\r
158                 /// </summary>\r
159                 public virtual CipherMode Mode {\r
160                         get {\r
161                                 return this.ModeValue;\r
162                         }\r
163                         set {\r
164                                 if (Enum.IsDefined(ModeValue.GetType(), value))\r
165                                         this.ModeValue = value;\r
166                                 else\r
167                                         throw new CryptographicException("padding mode not available");\r
168                         }\r
169                 }\r
170 \r
171                 /// <summary>\r
172                 /// Gets or sets the actual padding\r
173                 /// </summary>\r
174                 public virtual PaddingMode Padding {\r
175                         get {\r
176                                 return this.PaddingValue;\r
177                         }\r
178                         set {\r
179                                 if (Enum.IsDefined(PaddingValue.GetType(), value))\r
180                                         this.PaddingValue = value;\r
181                                 else\r
182                                         throw new CryptographicException("padding mode not available");\r
183                         }\r
184                 }\r
185 \r
186                 /// <summary>\r
187                 /// Gets an Decryptor transform object to work with a CryptoStream\r
188                 /// </summary>\r
189                 public virtual ICryptoTransform CreateDecryptor() {\r
190                         return CreateDecryptor(Key, IV);\r
191                 }\r
192 \r
193                 /// <summary>\r
194                 /// Gets an Decryptor transform object to work with a CryptoStream\r
195                 /// </summary>\r
196                 public abstract ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV);\r
197 \r
198                 /// <summary>\r
199                 /// Gets an Encryptor transform object to work with a CryptoStream\r
200                 /// </summary>\r
201                 public virtual ICryptoTransform CreateEncryptor() {\r
202                         return CreateEncryptor(Key, IV);\r
203                 }\r
204 \r
205                 /// <summary>\r
206                 /// Gets an Encryptor transform object to work with a CryptoStream\r
207                 /// </summary>\r
208                 public abstract ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV);\r
209 \r
210                 /// <summary>\r
211                 /// used to generate an inital vector if none is specified\r
212                 /// </summary>\r
213                 public abstract void GenerateIV();\r
214 \r
215                 /// </summary>\r
216                 /// used to generate a random key if none is specified\r
217                 /// </summary>\r
218                 public abstract void GenerateKey();\r
219 \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
223                                         if (i == Size)\r
224                                                 return true;\r
225                                 }\r
226                         }\r
227                         return false;\r
228                 }\r
229                 \r
230                 /// <summary>\r
231                 /// Checks wether the given keyLength is valid for the current algorithm\r
232                 /// </summary>\r
233                 /// <param name="bitLength">the given keyLength</param>\r
234                 public bool ValidKeySize(int bitLength) {\r
235                         return IsLegalKeySize(LegalKeySizesValue, bitLength);\r
236                 }\r
237                 \r
238                 /// <summary>\r
239                 /// Creates the default implementation of the default symmetric algorithm (RC2).\r
240                 /// </summary>\r
241                 public static SymmetricAlgorithm Create () {\r
242                         return Rijndael.Create();\r
243                 }\r
244         \r
245                 /// <summary>\r
246                 /// Creates a specific implementation of the given symmetric algorithm.\r
247                 /// </summary>\r
248                 /// <param name="algName">the given algorithm</param>\r
249                 [MonoTODO]\r
250                 public static SymmetricAlgorithm Create (string algName) {\r
251                         // TODO: Use Reflection to create a new algorithm instance\r
252                         return null;\r
253                 }\r
254         }\r
255 }\r
256 \r