2 // HMACSHA1Test.cs - NUnit Test Cases for HMACSHA1
5 // Sebastien Pouliot <sebastien@ximian.com>
7 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
8 // (C) 2004 Novell http://www.novell.com
11 using NUnit.Framework;
14 using System.Security.Cryptography;
17 namespace MonoTests.System.Security.Cryptography {
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
25 public class HMACSHA1Test : KeyedHashAlgorithmTest {
27 // protected HMACSHA1 hash;
30 public void Constructors ()
32 hash = new HMACSHA1 ();
33 AssertNotNull ("HMACSHA1 ()", hash);
35 byte[] key = new byte [8];
36 hash = new HMACSHA1 (key);
37 AssertNotNull ("HMACSHA1 (key)", hash);
41 [ExpectedException (typeof (NullReferenceException))]
42 public void Constructor_Null ()
44 hash = new HMACSHA1 (null);
48 public void Invariants ()
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 ());
60 #if (NET_1_0 || NET_1_1)
61 // this is legal in .NET 1.2 because HMACSHA1 derives from HMAC
63 [ExpectedException (typeof (InvalidCastException))]
64 public void Exceptions ()
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");
74 public void Check (string testName, byte[] key, byte[] data, byte[] result)
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);
84 public void CheckA (string testName, byte[] key, byte[] data, byte[] result)
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);
93 public void CheckB (string testName, byte[] key, byte[] data, byte[] result)
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);
102 public void CheckC (string testName, byte[] key, byte[] data, byte[] result)
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);
112 public void CheckD (string testName, byte[] key, byte[] data, byte[] result)
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);
121 public void CheckE (string testName, byte[] key, byte[] data, byte[] result)
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);
134 public void FIPS198_A1 ()
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 };
146 byte[] fips = { 0x4f, 0x4c, 0xa3, 0xd5, 0xd6, 0x8b, 0xa7, 0xcc, 0x0a, 0x12,
147 0x08, 0xc9, 0xc6, 0x1e, 0x9c, 0x5d, 0xa0, 0x40, 0x3c, 0x0a };
149 byte[] data = Encoding.Default.GetBytes ("Sample #1");
150 Check ("FIPS198-A1", key, data, fips);
154 public void FIPS198_A2 ()
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 };
160 byte[] fips = { 0x09, 0x22, 0xd3, 0x40, 0x5f, 0xaa, 0x3d, 0x19, 0x4f, 0x82,
161 0xa4, 0x58, 0x30, 0x73, 0x7d, 0x5c, 0xc6, 0xc7, 0x5d, 0x24 };
163 byte[] data = Encoding.Default.GetBytes ("Sample #2");
164 Check ("FIPS198-A2", key, data, fips);
168 public void FIPS198_A3 ()
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 };
179 byte[] fips = { 0xbc, 0xf4, 0x1e, 0xab, 0x8b, 0xb2, 0xd8, 0x02, 0xf3, 0xd0,
180 0x5c, 0xaf, 0x7c, 0xb0, 0x92, 0xec, 0xf8, 0xd1, 0xa3, 0xaa };
182 byte[] data = Encoding.Default.GetBytes ("Sample #3");
183 Check ("FIPS198-A3", key, data, fips);
187 public void FIPS198_A4 ()
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 };
195 byte[] fips = { 0x9e, 0xa8, 0x86, 0xef, 0xe2, 0x68, 0xdb, 0xec, 0xce, 0x42,
196 0x0c, 0x75, 0x24, 0xdf, 0x32, 0xe0, 0x75, 0x1a, 0x2a, 0x26 };
198 byte[] data = Encoding.Default.GetBytes ("Sample #4");
199 Check ("FIPS198-A4", key, data, fips);
203 public void RFC2202_TC1 ()
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);
212 public void RFC2202_TC2 ()
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);
221 public void RFC2202_TC3 ()
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++)
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);
232 public void RFC2202_TC4 ()
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++)
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);
243 public void RFC2202_TC5 ()
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);
252 public void RFC2202_TC6 ()
254 byte[] key = new byte [80];
255 for (int i = 0; i < key.Length; i++)
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);
263 public void RFC2202_TC7 ()
265 byte[] key = new byte [80];
266 for (int i = 0; i < key.Length; i++)
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);