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