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