cb689ea25edaf9eeffdd1f75d5ea31937fc2478b
[mono.git] / mcs / class / corlib / Test / System.Security.Cryptography / HashAlgorithmTest.cs
1 //
2 // HashAlgorithmTest.cs - NUnit Test Cases for HashAlgorithm
3 //
4 // Author:
5 //      Sebastien Pouliot  <sebastien@ximian.com>
6 //
7 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
8 // Copyright (C) 2004, 2006, 2007 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using NUnit.Framework;
31 using System;
32 using System.IO;
33 using System.Security.Cryptography;
34 using System.Text;
35
36 namespace MonoTests.System.Security.Cryptography {
37
38 // HashAlgorithm is a abstract class - so most of it's functionality wont
39 // be tested here (but will be in its descendants).
40
41 [TestFixture]
42 public class HashAlgorithmTest {
43
44         protected HashAlgorithm hash;
45
46         [SetUp]
47         public virtual void SetUp () 
48         {
49                 hash = HashAlgorithm.Create ();
50         }
51
52         // Note: These tests will only be valid without a "machine.config" file
53         // or a "machine.config" file that do not modify the default algorithm
54         // configuration.
55         private const string defaultSHA1 = "System.Security.Cryptography.SHA1CryptoServiceProvider";
56         private const string defaultMD5 = "System.Security.Cryptography.MD5CryptoServiceProvider";
57         private const string defaultSHA256 = "System.Security.Cryptography.SHA256Managed";
58         private const string defaultSHA384 = "System.Security.Cryptography.SHA384Managed";
59         private const string defaultSHA512 = "System.Security.Cryptography.SHA512Managed";
60         private const string defaultHash = defaultSHA1;
61
62         [Test]
63         public virtual void Create () 
64         {
65                 // try the default hash algorithm (created in SetUp)
66                 Assert.AreEqual (defaultHash, hash.ToString (), "HashAlgorithm.Create()");
67
68                 // try to build all hash algorithms
69                 hash = HashAlgorithm.Create ("SHA");
70                 Assert.AreEqual (defaultSHA1, hash.ToString (), "HashAlgorithm.Create('SHA')");
71                 hash = HashAlgorithm.Create ("SHA1");
72                 Assert.AreEqual (defaultSHA1, hash.ToString (), "HashAlgorithm.Create('SHA1')");
73                 hash = HashAlgorithm.Create ("System.Security.Cryptography.SHA1");
74                 Assert.AreEqual (defaultSHA1, hash.ToString (), "HashAlgorithm.Create('System.Security.Cryptography.SHA1')");
75                 hash = HashAlgorithm.Create ("System.Security.Cryptography.HashAlgorithm" );
76                 Assert.AreEqual (defaultHash, hash.ToString (), "HashAlgorithm.Create('System.Security.Cryptography.HashAlgorithm')");
77
78                 hash = HashAlgorithm.Create ("MD5");
79                 Assert.AreEqual (defaultMD5, hash.ToString (), "HashAlgorithm.Create('MD5')");
80                 hash = HashAlgorithm.Create ("System.Security.Cryptography.MD5");
81                 Assert.AreEqual (defaultMD5, hash.ToString (), "HashAlgorithm.Create('System.Security.Cryptography.MD5')");
82
83                 hash = HashAlgorithm.Create ("SHA256");
84                 Assert.AreEqual (defaultSHA256, hash.ToString (), "HashAlgorithm.Create('SHA256')");
85                 hash = HashAlgorithm.Create ("SHA-256");
86                 Assert.AreEqual (defaultSHA256, hash.ToString (), "HashAlgorithm.Create('SHA-256')");
87                 hash = HashAlgorithm.Create ("System.Security.Cryptography.SHA256");
88                 Assert.AreEqual (defaultSHA256, hash.ToString (), "HashAlgorithm.Create('System.Security.Cryptography.SHA256')");
89         
90                 hash = HashAlgorithm.Create ("SHA384");
91                 Assert.AreEqual (defaultSHA384, hash.ToString (), "HashAlgorithm.Create('SHA384')");
92                 hash = HashAlgorithm.Create ("SHA-384");
93                 Assert.AreEqual (defaultSHA384, hash.ToString (), "HashAlgorithm.Create('SHA-384')");
94                 hash = HashAlgorithm.Create ("System.Security.Cryptography.SHA384");
95                 Assert.AreEqual (defaultSHA384, hash.ToString (), "HashAlgorithm.Create('System.Security.Cryptography.SHA384')");
96         
97                 hash = HashAlgorithm.Create ("SHA512");
98                 Assert.AreEqual (defaultSHA512, hash.ToString (), "HashAlgorithm.Create('SHA512')");
99                 hash = HashAlgorithm.Create ("SHA-512");
100                 Assert.AreEqual (defaultSHA512, hash.ToString (), "HashAlgorithm.Create('SHA-512')");
101                 hash = HashAlgorithm.Create ("System.Security.Cryptography.SHA512");
102                 Assert.AreEqual (defaultSHA512, hash.ToString (), "HashAlgorithm.Create('System.Security.Cryptography.SHA512')");
103         
104                 // try to build invalid implementation
105                 hash = HashAlgorithm.Create ("InvalidHash");
106                 Assert.IsNull (hash, "HashAlgorithm.Create('InvalidHash')");
107         }
108
109         [Test]
110         [ExpectedException (typeof (ArgumentNullException))]
111         public virtual void CreateNull () 
112         {
113                 // try to build null implementation
114                 hash = HashAlgorithm.Create (null);
115         }
116
117         [Test]
118         [ExpectedException (typeof (ObjectDisposedException))]
119         public void Clear () 
120         {
121                 byte[] inputABC = Encoding.Default.GetBytes ("abc");
122                 hash.ComputeHash (inputABC);
123                 hash.Clear ();
124                 // cannot use a disposed object
125                 hash.ComputeHash (inputABC);
126         }
127
128         [Test]
129         [ExpectedException (typeof (ObjectDisposedException))]
130         public void Clear2 () 
131         {
132                 byte[] inputABC = Encoding.Default.GetBytes ("abc");
133                 MemoryStream ms = new MemoryStream (inputABC);
134                 hash.ComputeHash (ms);
135                 hash.Clear ();
136                 // cannot use a disposed object
137                 hash.ComputeHash (ms);
138         }
139
140         [Test]
141         [ExpectedException (typeof (NullReferenceException))]
142         public void NullStream () 
143         {
144                 Stream s = null;
145                 hash.ComputeHash (s);
146         }
147
148         [Test]
149         public void Disposable () 
150         {
151                 using (HashAlgorithm hash = HashAlgorithm.Create ()) {
152                         hash.ComputeHash (new byte [0]);
153                 }
154         }
155
156         [Test]
157         [ExpectedException (typeof (ObjectDisposedException))]
158         public void InitializeDisposed () 
159         {
160                 hash.ComputeHash (new byte [0]);
161                 hash.Clear (); // disposed
162                 hash.Initialize ();
163                 hash.ComputeHash (new byte [0]);
164         }
165
166         [Test]
167         [ExpectedException (typeof (ArgumentNullException))]
168         public void ComputeHash_ArrayNull ()
169         {
170                 byte[] array = null;
171                 hash.ComputeHash (array);
172         }
173
174         [Test]
175         [ExpectedException (typeof (ArgumentNullException))]
176         public void ComputeHash_ArrayNullIntInt ()
177         {
178                 byte[] array = null;
179                 hash.ComputeHash (array, 0, 0);
180         }
181
182         [Test]
183         [ExpectedException (typeof (ArgumentOutOfRangeException))]
184         public void ComputeHash_OffsetNegative ()
185         {
186                 byte[] array = new byte [0];
187                 hash.ComputeHash (array, -1, 0);
188         }
189
190         [Test]
191         [ExpectedException (typeof (ArgumentException))]
192         public void ComputeHash_OffsetOverflow ()
193         {
194                 byte[] array = new byte [1];
195                 hash.ComputeHash (array, Int32.MaxValue, 1);
196         }
197
198         [Test]
199         [ExpectedException (typeof (ArgumentException))]
200         public void ComputeHash_CountNegative ()
201         {
202                 byte[] array = new byte [0];
203                 hash.ComputeHash (array, 0, -1);
204         }
205
206         [Test]
207         [ExpectedException (typeof (ArgumentException))]
208         public void ComputeHash_CountOverflow ()
209         {
210                 byte[] array = new byte [1];
211                 hash.ComputeHash (array, 1, Int32.MaxValue);
212         }
213
214         [Test]
215 // not checked in Fx 1.1
216 //      [ExpectedException (typeof (ObjectDisposedException))]
217         public void TransformBlock_Disposed () 
218         {
219                 hash.ComputeHash (new byte [0]);
220                 hash.Initialize ();
221                 byte[] input = new byte [8];
222                 byte[] output = new byte [8];
223                 hash.TransformBlock (input, 0, input.Length, output, 0);
224         }
225
226         [Test]
227         [ExpectedException (typeof (ArgumentNullException))]
228         public void TransformBlock_InputBuffer_Null ()
229         {
230                 byte[] output = new byte [8];
231                 hash.TransformBlock (null, 0, output.Length, output, 0);
232         }
233
234         [Test]
235         [ExpectedException (typeof (ArgumentOutOfRangeException))]
236         public void TransformBlock_InputOffset_Negative ()
237         {
238                 byte[] input = new byte [8];
239                 byte[] output = new byte [8];
240                 hash.TransformBlock (input, -1, input.Length, output, 0);
241         }
242
243         [Test]
244         [ExpectedException (typeof (ArgumentException))]
245         public void TransformBlock_InputOffset_Overflow ()
246         {
247                 byte[] input = new byte [8];
248                 byte[] output = new byte [8];
249                 hash.TransformBlock (input, Int32.MaxValue, input.Length, output, 0);
250         }
251
252         [Test]
253         [ExpectedException (typeof (ArgumentException))]
254         public void TransformBlock_InputCount_Negative ()
255         {
256                 byte[] input = new byte [8];
257                 byte[] output = new byte [8];
258                 hash.TransformBlock (input, 0, -1, output, 0);
259         }
260
261         [Test]
262         [ExpectedException (typeof (ArgumentException))]
263         public void TransformBlock_InputCount_Overflow ()
264         {
265                 byte[] input = new byte [8];
266                 byte[] output = new byte [8];
267                 hash.TransformBlock (input, 0, Int32.MaxValue, output, 0);
268         }
269
270         [Test]
271         public void TransformBlock_OutputBuffer_Null ()
272         {
273                 byte[] input = new byte [8];
274                 hash.TransformBlock (input, 0, input.Length, null, 0);
275         }
276
277         [Test]
278         [ExpectedException (typeof (ArgumentOutOfRangeException))]
279         public void TransformBlock_OutputOffset_Negative ()
280         {
281                 byte[] input = new byte [8];
282                 byte[] output = new byte [8];
283                 hash.TransformBlock (input, 0, input.Length, output, -1);
284         }
285
286         [Test]
287         [ExpectedException (typeof (ArgumentException))]
288         public void TransformBlock_OutputOffset_Overflow ()
289         {
290                 byte[] input = new byte [8];
291                 byte[] output = new byte [8];
292                 hash.TransformBlock (input, 0, input.Length, output, Int32.MaxValue);
293         }
294
295         [Test]
296 // not checked in Fx 1.1
297 //      [ExpectedException (typeof (ObjectDisposedException))]
298         public void TransformFinalBlock_Disposed () 
299         {
300                 hash.ComputeHash (new byte [0]);
301                 hash.Initialize ();
302                 byte[] input = new byte [8];
303                 hash.TransformFinalBlock (input, 0, input.Length);
304         }
305
306         [Test]
307         [ExpectedException (typeof (ArgumentNullException))]
308         public void TransformFinalBlock_InputBuffer_Null ()
309         {
310                 hash.TransformFinalBlock (null, 0, 8);
311         }
312
313         [Test]
314         [ExpectedException (typeof (ArgumentOutOfRangeException))]
315         public void TransformFinalBlock_InputOffset_Negative ()
316         {
317                 byte[] input = new byte [8];
318                 hash.TransformFinalBlock (input, -1, input.Length);
319         }
320
321         [Test]
322         [ExpectedException (typeof (ArgumentException))]
323         public void TransformFinalBlock_InputOffset_Overflow ()
324         {
325                 byte[] input = new byte [8];
326                 hash.TransformFinalBlock (input, Int32.MaxValue, input.Length);
327         }
328
329         [Test]
330         [ExpectedException (typeof (ArgumentException))]
331         public void TransformFinalBlock_InputCount_Negative ()
332         {
333                 byte[] input = new byte [8];
334                 hash.TransformFinalBlock (input, 0, -1);
335         }
336
337         [Test]
338         [ExpectedException (typeof (ArgumentException))]
339         public void TransformFinalBlock_InputCount_Overflow ()
340         {
341                 byte[] input = new byte [8];
342                 hash.TransformFinalBlock (input, 0, Int32.MaxValue);
343         }
344
345         public virtual bool ManagedHashImplementation {
346                 get { return false; }
347         }
348 #if !NET_2_1
349         [Test]
350         [Category ("NotWorking")] // Mono nevers throws an exception (and we're all managed ;-)
351         public void TransformFinalBlock_Twice ()
352         {
353                 bool exception = false;
354                 byte[] input = new byte [8];
355                 hash.TransformFinalBlock (input, 0, input.Length);
356                 try {
357                         hash.TransformFinalBlock (input, 0, input.Length);
358                 }
359                 catch (CryptographicException) {
360                         exception = true;
361                         if (ManagedHashImplementation)
362                                 Assert.Fail ("*Managed don't throw CryptographicException");
363                 }
364                 if (!ManagedHashImplementation && !exception)
365                         Assert.Fail ("Expected CryptographicException from non *Managed classes");
366         }
367
368         [Test]
369         [Category ("NotWorking")] // Mono nevers throws an exception (and we're all managed ;-)
370         public void TransformFinalBlock_TransformBlock ()
371         {
372                 bool exception = false;
373                 byte[] input = new byte[8];
374                 hash.TransformFinalBlock (input, 0, input.Length);
375                 try {
376                         hash.TransformBlock (input, 0, input.Length, input, 0);
377                 }
378                 catch (CryptographicException) {
379                         exception = true;
380                         if (ManagedHashImplementation)
381                                 Assert.Fail ("*Managed don't throw CryptographicException");
382                 }
383                 if (!ManagedHashImplementation && !exception)
384                         Assert.Fail ("Expected CryptographicException from non *Managed classes");
385         }
386 #endif
387         [Test]
388         public void TransformFinalBlock_Twice_Initialize ()
389         {
390                 byte[] input = new byte[8];
391                 hash.TransformFinalBlock (input, 0, input.Length);
392                 hash.Initialize ();
393                 hash.TransformFinalBlock (input, 0, input.Length);
394         }
395
396         [Test]
397         public void TransformFinalBlock_ReturnedBuffer ()
398         {
399                 byte[] input = new byte[8];
400                 byte[] output = hash.TransformFinalBlock (input, 0, input.Length);
401                 Assert.AreEqual (input, output, "buffer");
402                 output[0] = 1;
403                 Assert.AreEqual (0, input[0], "0"); // output is a copy (not a reference)
404         }
405
406         private byte[] HashBuffer (bool intersect)
407         {
408                 byte[] buffer = new byte [256];
409                 for (int i = 0; i < buffer.Length; i++)
410                         buffer [i] = (byte) i;
411
412                 hash.Initialize ();
413                 // ok
414                 hash.TransformBlock (buffer, 0, 64, buffer, 0);
415                 // bad - we rewrite the beginning of the buffer
416                 hash.TransformBlock (buffer, 64, 128, buffer, intersect ? 0 : 64);
417                 // ok
418                 hash.TransformFinalBlock (buffer, 192, 64);
419                 return hash.Hash;
420         }
421
422         [Test]
423         public void InputOutputIntersection ()
424         {
425                 Assert.AreEqual (HashBuffer (false), HashBuffer (true), "Intersect");
426         }
427 #if !NET_2_1
428         [Test]
429         [ExpectedException (typeof (NullReferenceException))]
430         [Category ("NotWorking")] // initialization problem ? fx2.0 only ?
431         public void Hash_AfterInitialize_FirstTime ()
432         {
433                 hash.Initialize ();
434                 // getting the property throws
435                 Assert.IsNull (hash.Hash);
436         }
437 #endif
438         [Test]
439         [ExpectedException (typeof (CryptographicUnexpectedOperationException))]
440         public void Hash_AfterInitialize_SecondTime ()
441         {
442                 byte[] input = new byte[8];
443                 hash.Initialize ();
444                 hash.TransformBlock (input, 0, input.Length, input, 0);
445                 hash.Initialize ();
446                 // getting the property throws
447                 Assert.IsNull (hash.Hash);
448         }
449
450         [Test]
451         [ExpectedException (typeof (CryptographicUnexpectedOperationException))]
452         public void Hash_AfterTransformBlock ()
453         {
454                 byte[] input = new byte[8];
455                 hash.Initialize ();
456                 hash.TransformBlock (input, 0, input.Length, input, 0);
457                 // getting the property throws
458                 Assert.IsNull (hash.Hash);
459         }
460
461         [Test]
462         public void Hash_AfterTransformFinalBlock ()
463         {
464                 byte[] input = new byte[8];
465                 hash.Initialize ();
466                 hash.TransformFinalBlock (input, 0, input.Length);
467                 Assert.IsNotNull (hash.Hash);
468         }
469 }
470
471 }