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