New test.
[mono.git] / mcs / class / corlib / Test / System.Security.Cryptography / HMACSHA1Test.cs
1 //
2 // HMACSHA1Test.cs - NUnit Test Cases for HMACSHA1
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 // References:
39 // a.   The Keyed-Hash Message Authentication Code (HMAC)
40 //      http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
41 // b.   IETF RFC2202: Test Cases for HMAC-MD5 and HMAC-SHA-1
42 //      http://www.ietf.org/rfc/rfc2202.txt
43
44 public class HMACSHA1Test : KeyedHashAlgorithmTest {
45
46         protected HMACSHA1 algo;
47
48         [SetUp]
49         protected override void SetUp () 
50         {
51                 hash = HMACSHA1.Create ();
52                 (hash as KeyedHashAlgorithm).Key = new byte [8];
53         }
54
55         [Test]
56         public void Constructors () 
57         {
58                 algo = new HMACSHA1 ();
59                 AssertNotNull ("HMACSHA1 ()", hash);
60
61                 byte[] key = new byte [8];
62                 algo = new HMACSHA1 (key);
63                 AssertNotNull ("HMACSHA1 (key)", hash);
64         }
65
66         [Test]
67         [ExpectedException (typeof (NullReferenceException))]
68         public void Constructor_Null () 
69         {
70                 algo = new HMACSHA1 (null);
71         }
72
73         [Test]
74         public void Invariants () 
75         {
76                 algo = new HMACSHA1 ();
77                 AssertEquals ("HMACSHA1.CanReuseTransform", true, algo.CanReuseTransform);
78                 AssertEquals ("HMACSHA1.CanTransformMultipleBlocks", true, algo.CanTransformMultipleBlocks);
79                 AssertEquals ("HMACSHA1.HashName", "SHA1", algo.HashName);
80                 AssertEquals ("HMACSHA1.HashSize", 160, algo.HashSize);
81                 AssertEquals ("HMACSHA1.InputBlockSize", 1, algo.InputBlockSize);
82                 AssertEquals ("HMACSHA1.OutputBlockSize", 1, algo.OutputBlockSize);
83                 AssertEquals ("HMACSHA1.ToString()", "System.Security.Cryptography.HMACSHA1", algo.ToString ()); 
84         }
85
86 #if ! NET_2_0
87         // this is legal in .NET 2.0 because HMACSHA1 derives from HMAC
88         [Test]
89         [ExpectedException (typeof (InvalidCastException))]
90         public void InvalidHashName () 
91         {
92                 algo = new HMACSHA1 ();
93                 algo.HashName = "MD5";
94                 byte[] data = Encoding.Default.GetBytes ("MD5");
95                 byte[] hmac = algo.ComputeHash (data);
96         }
97 #endif
98
99         public void Check (string testName, byte[] key, byte[] data, byte[] result) 
100         {
101                 string classTestName = "HMACSHA1-" + testName;
102                 CheckA (testName, key, data, result);
103                 CheckB (testName, key, data, result);
104                 CheckC (testName, key, data, result);
105                 CheckD (testName, key, data, result);
106                 CheckE (testName, key, data, result);
107         }
108
109         public void CheckA (string testName, byte[] key, byte[] data, byte[] result) 
110         {
111 #if NET_2_0
112                 algo = new HMACSHA1 (key, true);
113 #else
114                 algo = new HMACSHA1 (key);
115 #endif
116                 byte[] hmac = algo.ComputeHash (data);
117                 AssertEquals (testName + "a1", result, hmac);
118                 AssertEquals (testName + "a2", result, algo.Hash);
119         }
120
121         public void CheckB (string testName, byte[] key, byte[] data, byte[] result) 
122         {
123 #if NET_2_0
124                 algo = new HMACSHA1 (key, false);
125 #else
126                 algo = new HMACSHA1 (key);
127 #endif
128                 byte[] hmac = algo.ComputeHash (data, 0, data.Length);
129                 AssertEquals (testName + "b1", result, hmac);
130                 AssertEquals (testName + "b2", result, algo.Hash);
131         }
132         
133         public void CheckC (string testName, byte[] key, byte[] data, byte[] result) 
134         {
135                 algo = new HMACSHA1 (key);
136                 MemoryStream ms = new MemoryStream (data);
137                 byte[] hmac = algo.ComputeHash (ms);
138                 AssertEquals (testName + "c1", result, hmac);
139                 AssertEquals (testName + "c2", result, algo.Hash);
140         }
141
142         public void CheckD (string testName, byte[] key, byte[] data, byte[] result) 
143         {
144                 algo = new HMACSHA1 (key);
145                 // LAMESPEC or FIXME: TransformFinalBlock doesn't return HashValue !
146                 algo.TransformFinalBlock (data, 0, data.Length);
147                 AssertEquals (testName + "d", result, algo.Hash);
148         }
149
150         public void CheckE (string testName, byte[] key, byte[] data, byte[] result) 
151         {
152                 algo = new HMACSHA1 (key);
153                 byte[] copy = new byte [data.Length];
154                 // LAMESPEC or FIXME: TransformFinalBlock doesn't return HashValue !
155                 for (int i=0; i < data.Length - 1; i++)
156                         algo.TransformBlock (data, i, 1, copy, i);
157                 algo.TransformFinalBlock (data, data.Length - 1, 1);
158                 AssertEquals (testName + "e", result, algo.Hash);
159         }
160
161         [Test]
162         public void FIPS198_A1 () 
163         {
164                 // exact 64 bytes key (no hashing - no padding)
165                 byte[] key =  { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
166                                 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
167                                 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
168                                 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
169                                 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
170                                 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
171                                 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
172                                 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f };
173
174                 byte[] fips = { 0x4f, 0x4c, 0xa3, 0xd5, 0xd6, 0x8b, 0xa7, 0xcc, 0x0a, 0x12,
175                                 0x08, 0xc9, 0xc6, 0x1e, 0x9c, 0x5d, 0xa0, 0x40, 0x3c, 0x0a };
176
177                 byte[] data = Encoding.Default.GetBytes ("Sample #1");
178                 Check ("FIPS198-A1", key, data, fips);
179         }
180
181         [Test]
182         public void FIPS198_A2 () 
183         {
184                 // key < 64 bytes -> requires padding
185                 byte[] key =  { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
186                                 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43 };
187
188                 byte[] fips = { 0x09, 0x22, 0xd3, 0x40, 0x5f, 0xaa, 0x3d, 0x19, 0x4f, 0x82,
189                                 0xa4, 0x58, 0x30, 0x73, 0x7d, 0x5c, 0xc6, 0xc7, 0x5d, 0x24 };
190
191                 byte[] data = Encoding.Default.GetBytes ("Sample #2");
192                 Check ("FIPS198-A2", key, data, fips);
193         }
194
195         [Test]
196         public void FIPS198_A3 () 
197         {
198                 // key > 64 bytes -> requires hashing
199                 byte[] key =  { 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
200                                 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
201                                 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
202                                 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
203                                 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
204                                 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
205                                 0xb0, 0xb1, 0xb2, 0xb3 };
206
207                 byte[] fips = { 0xbc, 0xf4, 0x1e, 0xab, 0x8b, 0xb2, 0xd8, 0x02, 0xf3, 0xd0,
208                                 0x5c, 0xaf, 0x7c, 0xb0, 0x92, 0xec, 0xf8, 0xd1, 0xa3, 0xaa };
209
210                 byte[] data = Encoding.Default.GetBytes ("Sample #3");
211                 Check ("FIPS198-A3", key, data, fips);
212         }
213
214         [Test]
215         public void FIPS198_A4 () 
216         {
217                 byte[] key =  { 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
218                                 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
219                                 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d,
220                                 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
221                                 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0 };
222
223                 byte[] fips = { 0x9e, 0xa8, 0x86, 0xef, 0xe2, 0x68, 0xdb, 0xec, 0xce, 0x42,
224                                 0x0c, 0x75, 0x24, 0xdf, 0x32, 0xe0, 0x75, 0x1a, 0x2a, 0x26 };
225
226                 byte[] data = Encoding.Default.GetBytes ("Sample #4");
227                 Check ("FIPS198-A4", key, data, fips);
228         }
229
230         [Test]
231         public void RFC2202_TC1 () 
232         {
233                 byte[] key =  { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b };
234                 byte[] data = Encoding.Default.GetBytes ("Hi There");
235                 byte[] digest = { 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, 0xf1, 0x46, 0xbe, 0x00 };
236                 Check ("RFC2202-TC1", key, data, digest);
237         }
238
239         [Test]
240         public void RFC2202_TC2 () 
241         {
242                 byte[] key = Encoding.Default.GetBytes ("Jefe");
243                 byte[] data = Encoding.Default.GetBytes ("what do ya want for nothing?");
244                 byte[] digest = { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74, 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79 };
245                 Check ("RFC2202-TC2", key, data, digest);
246         }
247
248         [Test]
249         public void RFC2202_TC3 () 
250         {
251                 byte[] key = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa };
252                 byte[] data = new byte [50];
253                 for (int i = 0; i < data.Length; i++)
254                         data[i] = 0xdd;
255                 byte[] digest = { 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3, 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1, 0x75, 0xd3 };
256                 Check ("RFC2202-TC3", key, data, digest);
257         }
258
259         [Test]
260         public void RFC2202_TC4 () 
261         {
262                 byte[] key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 };
263                 byte[] data = new byte [50];
264                 for (int i = 0; i < data.Length; i++)
265                         data[i] = 0xcd;
266                 byte[] digest = { 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, 0xbc, 0x84, 0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, 0x2d, 0x72, 0x35, 0xda };
267                 Check ("RFC2202-TC4", key, data, digest);
268         }
269
270         [Test]
271         public void RFC2202_TC5 () 
272         {
273                 byte[] key = { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c };
274                 byte[] data = Encoding.Default.GetBytes ("Test With Truncation");
275                 byte[] digest = { 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2, 0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04 };
276                 Check ("RFC2202-TC5", key, data, digest);
277         }
278
279         [Test]
280         public void RFC2202_TC6 () 
281         {
282                 byte[] key = new byte [80];
283                 for (int i = 0; i < key.Length; i++)
284                         key[i] = 0xaa;
285                 byte[] data = Encoding.Default.GetBytes ("Test Using Larger Than Block-Size Key - Hash Key First");
286                 byte[] digest = { 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40, 0x21, 0x12 };
287                 Check ("RFC2202-TC6", key, data, digest);
288         }
289
290         [Test]
291         public void RFC2202_TC7 () 
292         {
293                 byte[] key = new byte [80];
294                 for (int i = 0; i < key.Length; i++)
295                         key[i] = 0xaa;
296                 byte[] data = Encoding.Default.GetBytes ("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data");
297                 byte[] digest = { 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91 };
298                 Check ("RFC2202-TC7", key, data, digest);
299         }
300 }
301
302 }