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 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 // 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
44 public class HMACSHA1Test : KeyedHashAlgorithmTest {
46 protected HMACSHA1 algo;
49 protected override void SetUp ()
51 hash = HMACSHA1.Create ();
52 (hash as KeyedHashAlgorithm).Key = new byte [8];
56 public void Constructors ()
58 algo = new HMACSHA1 ();
59 AssertNotNull ("HMACSHA1 ()", hash);
61 byte[] key = new byte [8];
62 algo = new HMACSHA1 (key);
63 AssertNotNull ("HMACSHA1 (key)", hash);
67 [ExpectedException (typeof (NullReferenceException))]
68 public void Constructor_Null ()
70 algo = new HMACSHA1 (null);
74 public void Invariants ()
76 algo = new HMACSHA1 ();
77 AssertEquals ("HMACSHA1.CanReuseTransform", true, algo.CanReuseTransform);
78 AssertEquals ("HMACSHA1.CanTransformMultipleBlocks", true, algo.CanTransformMultipleBlocks);
79 AssertEquals ("HMACSHA1.HashName", "SHA1", algo.HashName);
80 AssertEquals ("HMACSHA1.HashSize", 160, algo.HashSize);
81 AssertEquals ("HMACSHA1.InputBlockSize", 1, algo.InputBlockSize);
82 AssertEquals ("HMACSHA1.OutputBlockSize", 1, algo.OutputBlockSize);
83 AssertEquals ("HMACSHA1.ToString()", "System.Security.Cryptography.HMACSHA1", algo.ToString ());
87 // this is legal in .NET 2.0 because HMACSHA1 derives from HMAC
89 [ExpectedException (typeof (InvalidCastException))]
90 public void InvalidHashName ()
92 algo = new HMACSHA1 ();
93 algo.HashName = "MD5";
94 byte[] data = Encoding.Default.GetBytes ("MD5");
95 byte[] hmac = algo.ComputeHash (data);
99 public void Check (string testName, byte[] key, byte[] data, byte[] result)
101 string classTestName = "HMACSHA1-" + testName;
102 CheckA (testName, key, data, result);
103 CheckB (testName, key, data, result);
104 CheckC (testName, key, data, result);
105 CheckD (testName, key, data, result);
106 CheckE (testName, key, data, result);
109 public void CheckA (string testName, byte[] key, byte[] data, byte[] result)
112 algo = new HMACSHA1 (key, true);
114 algo = new HMACSHA1 (key);
116 byte[] hmac = algo.ComputeHash (data);
117 AssertEquals (testName + "a1", result, hmac);
118 AssertEquals (testName + "a2", result, algo.Hash);
121 public void CheckB (string testName, byte[] key, byte[] data, byte[] result)
124 algo = new HMACSHA1 (key, false);
126 algo = new HMACSHA1 (key);
128 byte[] hmac = algo.ComputeHash (data, 0, data.Length);
129 AssertEquals (testName + "b1", result, hmac);
130 AssertEquals (testName + "b2", result, algo.Hash);
133 public void CheckC (string testName, byte[] key, byte[] data, byte[] result)
135 algo = new HMACSHA1 (key);
136 MemoryStream ms = new MemoryStream (data);
137 byte[] hmac = algo.ComputeHash (ms);
138 AssertEquals (testName + "c1", result, hmac);
139 AssertEquals (testName + "c2", result, algo.Hash);
142 public void CheckD (string testName, byte[] key, byte[] data, byte[] result)
144 algo = new HMACSHA1 (key);
145 // LAMESPEC or FIXME: TransformFinalBlock doesn't return HashValue !
146 algo.TransformFinalBlock (data, 0, data.Length);
147 AssertEquals (testName + "d", result, algo.Hash);
150 public void CheckE (string testName, byte[] key, byte[] data, byte[] result)
152 algo = new HMACSHA1 (key);
153 byte[] copy = new byte [data.Length];
154 // LAMESPEC or FIXME: TransformFinalBlock doesn't return HashValue !
155 for (int i=0; i < data.Length - 1; i++)
156 algo.TransformBlock (data, i, 1, copy, i);
157 algo.TransformFinalBlock (data, data.Length - 1, 1);
158 AssertEquals (testName + "e", result, algo.Hash);
162 public void FIPS198_A1 ()
164 // exact 64 bytes key (no hashing - no padding)
165 byte[] key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
166 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
167 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
168 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
169 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
170 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
171 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
172 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f };
174 byte[] fips = { 0x4f, 0x4c, 0xa3, 0xd5, 0xd6, 0x8b, 0xa7, 0xcc, 0x0a, 0x12,
175 0x08, 0xc9, 0xc6, 0x1e, 0x9c, 0x5d, 0xa0, 0x40, 0x3c, 0x0a };
177 byte[] data = Encoding.Default.GetBytes ("Sample #1");
178 Check ("FIPS198-A1", key, data, fips);
182 public void FIPS198_A2 ()
184 // key < 64 bytes -> requires padding
185 byte[] key = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
186 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43 };
188 byte[] fips = { 0x09, 0x22, 0xd3, 0x40, 0x5f, 0xaa, 0x3d, 0x19, 0x4f, 0x82,
189 0xa4, 0x58, 0x30, 0x73, 0x7d, 0x5c, 0xc6, 0xc7, 0x5d, 0x24 };
191 byte[] data = Encoding.Default.GetBytes ("Sample #2");
192 Check ("FIPS198-A2", key, data, fips);
196 public void FIPS198_A3 ()
198 // key > 64 bytes -> requires hashing
199 byte[] key = { 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
200 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
201 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
202 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
203 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
204 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
205 0xb0, 0xb1, 0xb2, 0xb3 };
207 byte[] fips = { 0xbc, 0xf4, 0x1e, 0xab, 0x8b, 0xb2, 0xd8, 0x02, 0xf3, 0xd0,
208 0x5c, 0xaf, 0x7c, 0xb0, 0x92, 0xec, 0xf8, 0xd1, 0xa3, 0xaa };
210 byte[] data = Encoding.Default.GetBytes ("Sample #3");
211 Check ("FIPS198-A3", key, data, fips);
215 public void FIPS198_A4 ()
217 byte[] key = { 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
218 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
219 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d,
220 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
221 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0 };
223 byte[] fips = { 0x9e, 0xa8, 0x86, 0xef, 0xe2, 0x68, 0xdb, 0xec, 0xce, 0x42,
224 0x0c, 0x75, 0x24, 0xdf, 0x32, 0xe0, 0x75, 0x1a, 0x2a, 0x26 };
226 byte[] data = Encoding.Default.GetBytes ("Sample #4");
227 Check ("FIPS198-A4", key, data, fips);
231 public void RFC2202_TC1 ()
233 byte[] key = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b };
234 byte[] data = Encoding.Default.GetBytes ("Hi There");
235 byte[] digest = { 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, 0xf1, 0x46, 0xbe, 0x00 };
236 Check ("RFC2202-TC1", key, data, digest);
240 public void RFC2202_TC2 ()
242 byte[] key = Encoding.Default.GetBytes ("Jefe");
243 byte[] data = Encoding.Default.GetBytes ("what do ya want for nothing?");
244 byte[] digest = { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74, 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79 };
245 Check ("RFC2202-TC2", key, data, digest);
249 public void RFC2202_TC3 ()
251 byte[] key = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa };
252 byte[] data = new byte [50];
253 for (int i = 0; i < data.Length; i++)
255 byte[] digest = { 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3, 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1, 0x75, 0xd3 };
256 Check ("RFC2202-TC3", key, data, digest);
260 public void RFC2202_TC4 ()
262 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 };
263 byte[] data = new byte [50];
264 for (int i = 0; i < data.Length; i++)
266 byte[] digest = { 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, 0xbc, 0x84, 0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, 0x2d, 0x72, 0x35, 0xda };
267 Check ("RFC2202-TC4", key, data, digest);
271 public void RFC2202_TC5 ()
273 byte[] key = { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c };
274 byte[] data = Encoding.Default.GetBytes ("Test With Truncation");
275 byte[] digest = { 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2, 0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04 };
276 Check ("RFC2202-TC5", key, data, digest);
280 public void RFC2202_TC6 ()
282 byte[] key = new byte [80];
283 for (int i = 0; i < key.Length; i++)
285 byte[] data = Encoding.Default.GetBytes ("Test Using Larger Than Block-Size Key - Hash Key First");
286 byte[] digest = { 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40, 0x21, 0x12 };
287 Check ("RFC2202-TC6", key, data, digest);
291 public void RFC2202_TC7 ()
293 byte[] key = new byte [80];
294 for (int i = 0; i < key.Length; i++)
296 byte[] data = Encoding.Default.GetBytes ("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data");
297 byte[] digest = { 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91 };
298 Check ("RFC2202-TC7", key, data, digest);