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 // Copyright (C) 2004, 2006, 2007 Novell, Inc (http://www.novell.com)
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:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
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.
30 using NUnit.Framework;
33 using System.Security.Cryptography;
36 namespace MonoTests.System.Security.Cryptography {
39 public class HS160 : HMACSHA1 {
41 public int BlockSize {
42 get { return base.BlockSizeValue; }
43 set { base.BlockSizeValue = value; }
49 // a. The Keyed-Hash Message Authentication Code (HMAC)
50 // http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
51 // b. IETF RFC2202: Test Cases for HMAC-MD5 and HMAC-SHA-1
52 // http://www.ietf.org/rfc/rfc2202.txt
54 public class HMACSHA1Test : KeyedHashAlgorithmTest {
56 protected HMACSHA1 algo;
59 public override void SetUp ()
61 hash = HMACSHA1.Create ();
62 (hash as KeyedHashAlgorithm).Key = new byte [8];
66 public void Constructors ()
68 algo = new HMACSHA1 ();
69 Assert.IsNotNull (hash, "HMACSHA1 ()");
71 byte[] key = new byte [8];
72 algo = new HMACSHA1 (key);
73 Assert.IsNotNull (hash, "HMACSHA1 (key)");
77 [ExpectedException (typeof (NullReferenceException))]
78 public void Constructor_Null ()
80 algo = new HMACSHA1 (null);
84 public void Invariants ()
86 algo = new HMACSHA1 ();
87 Assert.IsTrue (algo.CanReuseTransform, "HMACSHA1.CanReuseTransform");
88 Assert.IsTrue (algo.CanTransformMultipleBlocks, "HMACSHA1.CanTransformMultipleBlocks");
89 Assert.AreEqual ("SHA1", algo.HashName, "HMACSHA1.HashName");
90 Assert.AreEqual (160, algo.HashSize, "HMACSHA1.HashSize");
91 Assert.AreEqual (1, algo.InputBlockSize, "HMACSHA1.InputBlockSize");
92 Assert.AreEqual (1, algo.OutputBlockSize, "HMACSHA1.OutputBlockSize");
93 Assert.AreEqual ("System.Security.Cryptography.HMACSHA1", algo.ToString (), "HMACSHA1.ToString()");
98 public void BlockSize ()
100 HS160 hmac = new HS160 ();
101 Assert.AreEqual (64, hmac.BlockSize, "BlockSizeValue");
104 // this is legal in .NET 2.0 because HMACSHA1 derives from HMAC
106 [ExpectedException (typeof (InvalidCastException))]
107 public void InvalidHashName ()
109 algo = new HMACSHA1 ();
110 algo.HashName = "MD5";
111 byte[] data = Encoding.Default.GetBytes ("MD5");
112 byte[] hmac = algo.ComputeHash (data);
116 public void Check (string testName, byte[] key, byte[] data, byte[] result)
118 string classTestName = "HMACSHA1-" + testName;
119 CheckA (testName, key, data, result);
120 CheckB (testName, key, data, result);
121 CheckC (testName, key, data, result);
122 CheckD (testName, key, data, result);
123 CheckE (testName, key, data, result);
124 CheckF (testName, key, data, result);
127 public void CheckA (string testName, byte[] key, byte[] data, byte[] result)
130 algo = new HMACSHA1 (key, true);
132 algo = new HMACSHA1 (key);
134 byte[] hmac = algo.ComputeHash (data);
135 Assert.AreEqual (result, hmac, testName + "a1");
136 Assert.AreEqual (result, algo.Hash, testName + "a2");
139 public void CheckB (string testName, byte[] key, byte[] data, byte[] result)
142 algo = new HMACSHA1 (key, false);
144 algo = new HMACSHA1 (key);
146 byte[] hmac = algo.ComputeHash (data, 0, data.Length);
147 Assert.AreEqual (result, hmac, testName + "b1");
148 Assert.AreEqual (result, algo.Hash, testName + "b2");
151 public void CheckC (string testName, byte[] key, byte[] data, byte[] result)
153 algo = new HMACSHA1 (key);
154 MemoryStream ms = new MemoryStream (data);
155 byte[] hmac = algo.ComputeHash (ms);
156 Assert.AreEqual (result, hmac, testName + "c1");
157 Assert.AreEqual (result, algo.Hash, testName + "c2");
160 public void CheckD (string testName, byte[] key, byte[] data, byte[] result)
162 algo = new HMACSHA1 (key);
163 // LAMESPEC or FIXME: TransformFinalBlock doesn't return HashValue !
164 algo.TransformFinalBlock (data, 0, data.Length);
165 Assert.AreEqual (result, algo.Hash, testName + "d");
168 public void CheckE (string testName, byte[] key, byte[] data, byte[] result)
170 algo = new HMACSHA1 (key);
171 byte[] copy = new byte [data.Length];
172 // LAMESPEC or FIXME: TransformFinalBlock doesn't return HashValue !
173 for (int i=0; i < data.Length - 1; i++)
174 algo.TransformBlock (data, i, 1, copy, i);
175 algo.TransformFinalBlock (data, data.Length - 1, 1);
176 Assert.AreEqual (result, algo.Hash, testName + "e");
179 public void CheckF (string testName, byte[] key, byte[] data, byte[] result)
181 algo = new HMACSHA1 (key);
182 byte[] temp = new byte[data.Length + 2];
183 for (int i = 0; i < data.Length; i ++)
184 temp[i + 1] = data[i];
185 byte[] hmac = algo.ComputeHash (temp, 1, data.Length);
186 Assert.AreEqual (result, hmac, testName + "f");
190 public void FIPS198_A1 ()
192 // exact 64 bytes key (no hashing - no padding)
193 byte[] key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
194 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
195 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
196 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
197 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
198 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
199 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
200 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f };
202 byte[] fips = { 0x4f, 0x4c, 0xa3, 0xd5, 0xd6, 0x8b, 0xa7, 0xcc, 0x0a, 0x12,
203 0x08, 0xc9, 0xc6, 0x1e, 0x9c, 0x5d, 0xa0, 0x40, 0x3c, 0x0a };
205 byte[] data = Encoding.Default.GetBytes ("Sample #1");
206 Check ("FIPS198-A1", key, data, fips);
210 public void FIPS198_A2 ()
212 // key < 64 bytes -> requires padding
213 byte[] key = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
214 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43 };
216 byte[] fips = { 0x09, 0x22, 0xd3, 0x40, 0x5f, 0xaa, 0x3d, 0x19, 0x4f, 0x82,
217 0xa4, 0x58, 0x30, 0x73, 0x7d, 0x5c, 0xc6, 0xc7, 0x5d, 0x24 };
219 byte[] data = Encoding.Default.GetBytes ("Sample #2");
220 Check ("FIPS198-A2", key, data, fips);
224 public void FIPS198_A3 ()
226 // key > 64 bytes -> requires hashing
227 byte[] key = { 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
228 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
229 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
230 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
231 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
232 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
233 0xb0, 0xb1, 0xb2, 0xb3 };
235 byte[] fips = { 0xbc, 0xf4, 0x1e, 0xab, 0x8b, 0xb2, 0xd8, 0x02, 0xf3, 0xd0,
236 0x5c, 0xaf, 0x7c, 0xb0, 0x92, 0xec, 0xf8, 0xd1, 0xa3, 0xaa };
238 byte[] data = Encoding.Default.GetBytes ("Sample #3");
239 Check ("FIPS198-A3", key, data, fips);
243 public void FIPS198_A4 ()
245 byte[] key = { 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
246 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
247 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d,
248 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
249 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0 };
251 byte[] fips = { 0x9e, 0xa8, 0x86, 0xef, 0xe2, 0x68, 0xdb, 0xec, 0xce, 0x42,
252 0x0c, 0x75, 0x24, 0xdf, 0x32, 0xe0, 0x75, 0x1a, 0x2a, 0x26 };
254 byte[] data = Encoding.Default.GetBytes ("Sample #4");
255 Check ("FIPS198-A4", key, data, fips);
259 public void RFC2202_TC1 ()
261 byte[] key = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b };
262 byte[] data = Encoding.Default.GetBytes ("Hi There");
263 byte[] digest = { 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, 0xf1, 0x46, 0xbe, 0x00 };
264 Check ("RFC2202-TC1", key, data, digest);
268 public void RFC2202_TC2 ()
270 byte[] key = Encoding.Default.GetBytes ("Jefe");
271 byte[] data = Encoding.Default.GetBytes ("what do ya want for nothing?");
272 byte[] digest = { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74, 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79 };
273 Check ("RFC2202-TC2", key, data, digest);
277 public void RFC2202_TC3 ()
279 byte[] key = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa };
280 byte[] data = new byte [50];
281 for (int i = 0; i < data.Length; i++)
283 byte[] digest = { 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3, 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1, 0x75, 0xd3 };
284 Check ("RFC2202-TC3", key, data, digest);
288 public void RFC2202_TC4 ()
290 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 };
291 byte[] data = new byte [50];
292 for (int i = 0; i < data.Length; i++)
294 byte[] digest = { 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, 0xbc, 0x84, 0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, 0x2d, 0x72, 0x35, 0xda };
295 Check ("RFC2202-TC4", key, data, digest);
299 public void RFC2202_TC5 ()
301 byte[] key = { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c };
302 byte[] data = Encoding.Default.GetBytes ("Test With Truncation");
303 byte[] digest = { 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2, 0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04 };
304 Check ("RFC2202-TC5", key, data, digest);
308 public void RFC2202_TC6 ()
310 byte[] key = new byte [80];
311 for (int i = 0; i < key.Length; i++)
313 byte[] data = Encoding.Default.GetBytes ("Test Using Larger Than Block-Size Key - Hash Key First");
314 byte[] digest = { 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40, 0x21, 0x12 };
315 Check ("RFC2202-TC6", key, data, digest);
319 public void RFC2202_TC7 ()
321 byte[] key = new byte [80];
322 for (int i = 0; i < key.Length; i++)
324 byte[] data = Encoding.Default.GetBytes ("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data");
325 byte[] digest = { 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91 };
326 Check ("RFC2202-TC7", key, data, digest);