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