New test.
[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 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 : Assertion {
43         protected HashAlgorithm hash;
44
45         [SetUp]
46         protected virtual void SetUp () 
47         {
48                 hash = HashAlgorithm.Create ();
49         }
50
51         public void AssertEquals (string msg, byte[] array1, byte[] array2) 
52         {
53                 AllTests.AssertEquals (msg, array1, array2);
54         }
55
56         // Note: These tests will only be valid without a "machine.config" file
57         // or a "machine.config" file that do not modify the default algorithm
58         // configuration.
59         private const string defaultSHA1 = "System.Security.Cryptography.SHA1CryptoServiceProvider";
60         private const string defaultMD5 = "System.Security.Cryptography.MD5CryptoServiceProvider";
61         private const string defaultSHA256 = "System.Security.Cryptography.SHA256Managed";
62         private const string defaultSHA384 = "System.Security.Cryptography.SHA384Managed";
63         private const string defaultSHA512 = "System.Security.Cryptography.SHA512Managed";
64         private const string defaultHash = defaultSHA1;
65
66         [Test]
67         public virtual void Create () 
68         {
69                 // try the default hash algorithm (created in SetUp)
70                 AssertEquals( "HashAlgorithm.Create()", defaultHash, hash.ToString());
71
72                 // try to build all hash algorithms
73                 hash = HashAlgorithm.Create ("SHA");
74                 AssertEquals ("HashAlgorithm.Create('SHA')", defaultSHA1, hash.ToString ());
75                 hash = HashAlgorithm.Create ("SHA1");
76                 AssertEquals ("HashAlgorithm.Create('SHA1')", defaultSHA1, hash.ToString ());
77                 hash = HashAlgorithm.Create ("System.Security.Cryptography.SHA1");
78                 AssertEquals ("HashAlgorithm.Create('System.Security.Cryptography.SHA1')", defaultSHA1, hash.ToString ());
79                 hash = HashAlgorithm.Create ("System.Security.Cryptography.HashAlgorithm" );
80                 AssertEquals ("HashAlgorithm.Create('System.Security.Cryptography.HashAlgorithm')", defaultHash, hash.ToString ());
81
82                 hash = HashAlgorithm.Create ("MD5");
83                 AssertEquals ("HashAlgorithm.Create('MD5')", defaultMD5, hash.ToString ());
84                 hash = HashAlgorithm.Create ("System.Security.Cryptography.MD5");
85                 AssertEquals ("HashAlgorithm.Create('System.Security.Cryptography.MD5')", defaultMD5, hash.ToString ());
86
87                 hash = HashAlgorithm.Create ("SHA256");
88                 AssertEquals ("HashAlgorithm.Create('SHA256')", defaultSHA256, hash.ToString ());
89                 hash = HashAlgorithm.Create ("SHA-256");
90                 AssertEquals ("HashAlgorithm.Create('SHA-256')", defaultSHA256, hash.ToString ());
91                 hash = HashAlgorithm.Create ("System.Security.Cryptography.SHA256");
92                 AssertEquals ("HashAlgorithm.Create('System.Security.Cryptography.SHA256')", defaultSHA256, hash.ToString ());
93         
94                 hash = HashAlgorithm.Create ("SHA384");
95                 AssertEquals ("HashAlgorithm.Create('SHA384')", defaultSHA384, hash.ToString ());
96                 hash = HashAlgorithm.Create ("SHA-384");
97                 AssertEquals ("HashAlgorithm.Create('SHA-384')", defaultSHA384, hash.ToString ());
98                 hash = HashAlgorithm.Create ("System.Security.Cryptography.SHA384");
99                 AssertEquals ("HashAlgorithm.Create('System.Security.Cryptography.SHA384')", defaultSHA384, hash.ToString ());
100         
101                 hash = HashAlgorithm.Create ("SHA512");
102                 AssertEquals ("HashAlgorithm.Create('SHA512')", defaultSHA512, hash.ToString ());
103                 hash = HashAlgorithm.Create ("SHA-512");
104                 AssertEquals ("HashAlgorithm.Create('SHA-512')", defaultSHA512, hash.ToString ());
105                 hash = HashAlgorithm.Create ("System.Security.Cryptography.SHA512");
106                 AssertEquals ("HashAlgorithm.Create('System.Security.Cryptography.SHA512')", defaultSHA512, hash.ToString ());
107         
108                 // try to build invalid implementation
109                 hash = HashAlgorithm.Create ("InvalidHash");
110                 AssertNull ("HashAlgorithm.Create('InvalidHash')", hash);
111         }
112
113         [Test]
114         [ExpectedException (typeof (ArgumentNullException))]
115         public virtual void CreateNull () 
116         {
117                 // try to build null implementation
118                 hash = HashAlgorithm.Create (null);
119         }
120
121         [Test]
122         [ExpectedException (typeof (ObjectDisposedException))]
123         public void Clear () 
124         {
125                 byte[] inputABC = Encoding.Default.GetBytes ("abc");
126                 hash.ComputeHash (inputABC);
127                 hash.Clear ();
128                 // cannot use a disposed object
129                 hash.ComputeHash (inputABC);
130         }
131
132         [Test]
133         [ExpectedException (typeof (ObjectDisposedException))]
134         public void Clear2 () 
135         {
136                 byte[] inputABC = Encoding.Default.GetBytes ("abc");
137                 MemoryStream ms = new MemoryStream (inputABC);
138                 hash.ComputeHash (ms);
139                 hash.Clear ();
140                 // cannot use a disposed object
141                 hash.ComputeHash (ms);
142         }
143
144         [Test]
145         [ExpectedException (typeof (NullReferenceException))]
146         public void NullStream () 
147         {
148                 Stream s = null;
149                 byte[] result = hash.ComputeHash (s);
150         }
151
152         [Test]
153         public void Disposable () 
154         {
155                 using (HashAlgorithm hash = HashAlgorithm.Create ()) {
156                         byte[] data = hash.ComputeHash (new byte [0]);
157                 }
158         }
159
160         [Test]
161         [ExpectedException (typeof (ObjectDisposedException))]
162         public void InitializeDisposed () 
163         {
164                 hash.ComputeHash (new byte [0]);
165                 hash.Clear (); // disposed
166                 hash.Initialize ();
167                 hash.ComputeHash (new byte [0]);
168         }
169
170         [Test]
171         [ExpectedException (typeof (ArgumentNullException))]
172         public void ComputeHash_ArrayNull ()
173         {
174                 byte[] array = null;
175                 hash.ComputeHash (array);
176         }
177
178         [Test]
179         [ExpectedException (typeof (ArgumentNullException))]
180         public void ComputeHash_ArrayNullIntInt ()
181         {
182                 byte[] array = null;
183                 hash.ComputeHash (array, 0, 0);
184         }
185
186         [Test]
187         [ExpectedException (typeof (ArgumentOutOfRangeException))]
188         public void ComputeHash_OffsetNegative ()
189         {
190                 byte[] array = new byte [0];
191                 hash.ComputeHash (array, -1, 0);
192         }
193
194         [Test]
195         [ExpectedException (typeof (ArgumentException))]
196         public void ComputeHash_OffsetOverflow ()
197         {
198                 byte[] array = new byte [1];
199                 hash.ComputeHash (array, Int32.MaxValue, 1);
200         }
201
202         [Test]
203         [ExpectedException (typeof (ArgumentException))]
204         public void ComputeHash_CountNegative ()
205         {
206                 byte[] array = new byte [0];
207                 hash.ComputeHash (array, 0, -1);
208         }
209
210         [Test]
211         [ExpectedException (typeof (ArgumentException))]
212         public void ComputeHash_CountOverflow ()
213         {
214                 byte[] array = new byte [1];
215                 hash.ComputeHash (array, 1, Int32.MaxValue);
216         }
217
218         [Test]
219 // not checked in Fx 1.1
220 //      [ExpectedException (typeof (ObjectDisposedException))]
221         public void TransformBlock_Disposed () 
222         {
223                 hash.ComputeHash (new byte [0]);
224                 hash.Initialize ();
225                 byte[] input = new byte [8];
226                 byte[] output = new byte [8];
227                 hash.TransformBlock (input, 0, input.Length, output, 0);
228         }
229
230         [Test]
231         [ExpectedException (typeof (ArgumentNullException))]
232         public void TransformBlock_InputBuffer_Null ()
233         {
234                 byte[] output = new byte [8];
235                 hash.TransformBlock (null, 0, output.Length, output, 0);
236         }
237
238         [Test]
239         [ExpectedException (typeof (ArgumentOutOfRangeException))]
240         public void TransformBlock_InputOffset_Negative ()
241         {
242                 byte[] input = new byte [8];
243                 byte[] output = new byte [8];
244                 hash.TransformBlock (input, -1, input.Length, output, 0);
245         }
246
247         [Test]
248         [ExpectedException (typeof (ArgumentException))]
249         public void TransformBlock_InputOffset_Overflow ()
250         {
251                 byte[] input = new byte [8];
252                 byte[] output = new byte [8];
253                 hash.TransformBlock (input, Int32.MaxValue, input.Length, output, 0);
254         }
255
256         [Test]
257         [ExpectedException (typeof (ArgumentException))]
258         public void TransformBlock_InputCount_Negative ()
259         {
260                 byte[] input = new byte [8];
261                 byte[] output = new byte [8];
262                 hash.TransformBlock (input, 0, -1, output, 0);
263         }
264
265         [Test]
266         [ExpectedException (typeof (ArgumentException))]
267         public void TransformBlock_InputCount_Overflow ()
268         {
269                 byte[] input = new byte [8];
270                 byte[] output = new byte [8];
271                 hash.TransformBlock (input, 0, Int32.MaxValue, output, 0);
272         }
273
274         [Test]
275 #if ONLY_1_1
276         [Category ("NotDotNet")] // System.ExecutionEngineException on MS runtime (1.1)
277 #endif
278         public void TransformBlock_OutputBuffer_Null ()
279         {
280                 byte[] input = new byte [8];
281                 hash.TransformBlock (input, 0, input.Length, null, 0);
282         }
283
284         [Test]
285 #if NET_2_0
286         [ExpectedException (typeof (ArgumentOutOfRangeException))]
287 #else
288         [ExpectedException (typeof (IndexOutOfRangeException))]
289 #endif
290         public void TransformBlock_OutputOffset_Negative ()
291         {
292                 byte[] input = new byte [8];
293                 byte[] output = new byte [8];
294                 hash.TransformBlock (input, 0, input.Length, output, -1);
295         }
296
297         [Test]
298 #if NET_2_0
299         [ExpectedException (typeof (ArgumentException))]
300 #else
301         [ExpectedException (typeof (IndexOutOfRangeException))]
302 #endif
303         public void TransformBlock_OutputOffset_Overflow ()
304         {
305                 byte[] input = new byte [8];
306                 byte[] output = new byte [8];
307                 hash.TransformBlock (input, 0, input.Length, output, Int32.MaxValue);
308         }
309
310         [Test]
311 // not checked in Fx 1.1
312 //      [ExpectedException (typeof (ObjectDisposedException))]
313         public void TransformFinalBlock_Disposed () 
314         {
315                 hash.ComputeHash (new byte [0]);
316                 hash.Initialize ();
317                 byte[] input = new byte [8];
318                 hash.TransformFinalBlock (input, 0, input.Length);
319         }
320
321         [Test]
322         [ExpectedException (typeof (ArgumentNullException))]
323         public void TransformFinalBlock_InputBuffer_Null ()
324         {
325                 hash.TransformFinalBlock (null, 0, 8);
326         }
327
328         [Test]
329         [ExpectedException (typeof (ArgumentOutOfRangeException))]
330         public void TransformFinalBlock_InputOffset_Negative ()
331         {
332                 byte[] input = new byte [8];
333                 hash.TransformFinalBlock (input, -1, input.Length);
334         }
335
336         [Test]
337         [ExpectedException (typeof (ArgumentException))]
338         public void TransformFinalBlock_InputOffset_Overflow ()
339         {
340                 byte[] input = new byte [8];
341                 hash.TransformFinalBlock (input, Int32.MaxValue, input.Length);
342         }
343
344         [Test]
345         [ExpectedException (typeof (ArgumentException))]
346         public void TransformFinalBlock_InputCount_Negative ()
347         {
348                 byte[] input = new byte [8];
349                 hash.TransformFinalBlock (input, 0, -1);
350         }
351
352         [Test]
353         [ExpectedException (typeof (ArgumentException))]
354         public void TransformFinalBlock_InputCount_Overflow ()
355         {
356                 byte[] input = new byte [8];
357                 hash.TransformFinalBlock (input, 0, Int32.MaxValue);
358         }
359
360         [Test]
361         [Category ("NotWorking")] // Mono nevers throws an exception (and we're all managed ;-)
362         public void TransformFinalBlock_Twice ()
363         {
364                 bool managed = (hash.GetType ().ToString ().IndexOf ("Managed") > 0);
365                 bool exception = false;
366                 byte[] input = new byte [8];
367                 hash.TransformFinalBlock (input, 0, input.Length);
368                 try {
369                         hash.TransformFinalBlock (input, 0, input.Length);
370                 }
371                 catch (CryptographicException) {
372                         exception = true;
373                         if (managed)
374                                 Fail ("*Managed don't throw CryptographicException");
375                 }
376                 if (!managed && !exception)
377                         Fail ("Expected CryptographicException from non *Managed classes");
378         }
379
380         [Test]
381         [Category ("NotWorking")] // Mono nevers throws an exception (and we're all managed ;-)
382         public void TransformFinalBlock_TransformBlock ()
383         {
384                 bool managed = (hash.GetType ().ToString ().IndexOf ("Managed") > 0);
385                 bool exception = false;
386                 byte[] input = new byte[8];
387                 hash.TransformFinalBlock (input, 0, input.Length);
388                 try {
389                         hash.TransformBlock (input, 0, input.Length, input, 0);
390                 }
391                 catch (CryptographicException) {
392                         exception = true;
393                         if (managed)
394                                 Fail ("*Managed don't throw CryptographicException");
395                 }
396                 if (!managed && !exception)
397                         Fail ("Expected CryptographicException from non *Managed classes");
398         }
399
400         [Test]
401         public void TransformFinalBlock_Twice_Initialize ()
402         {
403                 byte[] input = new byte[8];
404                 hash.TransformFinalBlock (input, 0, input.Length);
405                 hash.Initialize ();
406                 hash.TransformFinalBlock (input, 0, input.Length);
407         }
408
409         [Test]
410         public void TransformFinalBlock_ReturnedBuffer ()
411         {
412                 byte[] input = new byte[8];
413                 byte[] output = hash.TransformFinalBlock (input, 0, input.Length);
414                 AssertEquals ("buffer", input, output);
415                 output[0] = 1;
416                 AssertEquals ("0", 0, input[0]); // output is a copy (not a reference)
417         }
418
419         private byte[] HashBuffer (bool intersect)
420         {
421                 byte[] buffer = new byte [256];
422                 for (int i = 0; i < buffer.Length; i++)
423                         buffer [i] = (byte) i;
424
425                 hash.Initialize ();
426                 // ok
427                 hash.TransformBlock (buffer, 0, 64, buffer, 0);
428                 // bad - we rewrite the beginning of the buffer
429                 hash.TransformBlock (buffer, 64, 128, buffer, intersect ? 0 : 64);
430                 // ok
431                 hash.TransformFinalBlock (buffer, 192, 64);
432                 return hash.Hash;
433         }
434
435         [Test]
436         public void InputOutputIntersection ()
437         {
438                 AssertEquals ("Intersect", HashBuffer (false), HashBuffer (true));
439         }
440
441         [Test]
442         [ExpectedException (typeof (NullReferenceException))]
443         [Category ("NotWorking")] // initialization problem ? fx2.0 only ?
444         public void Hash_AfterInitialize_FirstTime ()
445         {
446                 hash.Initialize ();
447                 // getting the property throws
448                 AssertNull (hash.Hash);
449         }
450
451         [Test]
452         [ExpectedException (typeof (CryptographicUnexpectedOperationException))]
453         public void Hash_AfterInitialize_SecondTime ()
454         {
455                 byte[] input = new byte[8];
456                 hash.Initialize ();
457                 hash.TransformBlock (input, 0, input.Length, input, 0);
458                 hash.Initialize ();
459                 // getting the property throws
460                 AssertNull (hash.Hash);
461         }
462
463         [Test]
464         [ExpectedException (typeof (CryptographicUnexpectedOperationException))]
465         public void Hash_AfterTransformBlock ()
466         {
467                 byte[] input = new byte[8];
468                 hash.Initialize ();
469                 hash.TransformBlock (input, 0, input.Length, input, 0);
470                 // getting the property throws
471                 AssertNull (hash.Hash);
472         }
473
474         [Test]
475         public void Hash_AfterTransformFinalBlock ()
476         {
477                 byte[] input = new byte[8];
478                 hash.Initialize ();
479                 hash.TransformFinalBlock (input, 0, input.Length);
480                 AssertNotNull (hash.Hash);
481         }
482 }
483
484 }