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 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 public void Constructors ()
51 algo = new HMACSHA1 ();
52 AssertNotNull ("HMACSHA1 ()", hash);
54 byte[] key = new byte [8];
55 algo = new HMACSHA1 (key);
56 AssertNotNull ("HMACSHA1 (key)", hash);
60 [ExpectedException (typeof (NullReferenceException))]
61 public void Constructor_Null ()
63 algo = new HMACSHA1 (null);
67 public void Invariants ()
69 algo = new HMACSHA1 ();
70 AssertEquals ("HMACSHA1.CanReuseTransform", true, algo.CanReuseTransform);
71 AssertEquals ("HMACSHA1.CanTransformMultipleBlocks", true, algo.CanTransformMultipleBlocks);
72 AssertEquals ("HMACSHA1.HashName", "SHA1", algo.HashName);
73 AssertEquals ("HMACSHA1.HashSize", 160, algo.HashSize);
74 AssertEquals ("HMACSHA1.InputBlockSize", 1, algo.InputBlockSize);
75 AssertEquals ("HMACSHA1.OutputBlockSize", 1, algo.OutputBlockSize);
76 AssertEquals ("HMACSHA1.ToString()", "System.Security.Cryptography.HMACSHA1", algo.ToString ());
80 // this is legal in .NET 2.0 because HMACSHA1 derives from HMAC
82 [ExpectedException (typeof (InvalidCastException))]
83 public void InvalidHashName ()
85 algo = new HMACSHA1 ();
86 algo.HashName = "MD5";
87 byte[] data = Encoding.Default.GetBytes ("MD5");
88 byte[] hmac = algo.ComputeHash (data);
92 public void Check (string testName, byte[] key, byte[] data, byte[] result)
94 string classTestName = "HMACSHA1-" + testName;
95 CheckA (testName, key, data, result);
96 CheckB (testName, key, data, result);
97 CheckC (testName, key, data, result);
98 CheckD (testName, key, data, result);
99 CheckE (testName, key, data, result);
102 public void CheckA (string testName, byte[] key, byte[] data, byte[] result)
105 algo = new HMACSHA1 (key, true);
107 algo = new HMACSHA1 (key);
109 byte[] hmac = algo.ComputeHash (data);
110 AssertEquals (testName + "a1", result, hmac);
111 AssertEquals (testName + "a2", result, algo.Hash);
114 public void CheckB (string testName, byte[] key, byte[] data, byte[] result)
117 algo = new HMACSHA1 (key, false);
119 algo = new HMACSHA1 (key);
121 byte[] hmac = algo.ComputeHash (data, 0, data.Length);
122 AssertEquals (testName + "b1", result, hmac);
123 AssertEquals (testName + "b2", result, algo.Hash);
126 public void CheckC (string testName, byte[] key, byte[] data, byte[] result)
128 algo = new HMACSHA1 (key);
129 MemoryStream ms = new MemoryStream (data);
130 byte[] hmac = algo.ComputeHash (ms);
131 AssertEquals (testName + "c1", result, hmac);
132 AssertEquals (testName + "c2", result, algo.Hash);
135 public void CheckD (string testName, byte[] key, byte[] data, byte[] result)
137 algo = new HMACSHA1 (key);
138 // LAMESPEC or FIXME: TransformFinalBlock doesn't return HashValue !
139 algo.TransformFinalBlock (data, 0, data.Length);
140 AssertEquals (testName + "d", result, algo.Hash);
143 public void CheckE (string testName, byte[] key, byte[] data, byte[] result)
145 algo = new HMACSHA1 (key);
146 byte[] copy = new byte [data.Length];
147 // LAMESPEC or FIXME: TransformFinalBlock doesn't return HashValue !
148 for (int i=0; i < data.Length - 1; i++)
149 algo.TransformBlock (data, i, 1, copy, i);
150 algo.TransformFinalBlock (data, data.Length - 1, 1);
151 AssertEquals (testName + "e", result, algo.Hash);
155 public void FIPS198_A1 ()
157 // exact 64 bytes key (no hashing - no padding)
158 byte[] key = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
159 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
160 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
161 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
162 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
163 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
164 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
165 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f };
167 byte[] fips = { 0x4f, 0x4c, 0xa3, 0xd5, 0xd6, 0x8b, 0xa7, 0xcc, 0x0a, 0x12,
168 0x08, 0xc9, 0xc6, 0x1e, 0x9c, 0x5d, 0xa0, 0x40, 0x3c, 0x0a };
170 byte[] data = Encoding.Default.GetBytes ("Sample #1");
171 Check ("FIPS198-A1", key, data, fips);
175 public void FIPS198_A2 ()
177 // key < 64 bytes -> requires padding
178 byte[] key = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
179 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43 };
181 byte[] fips = { 0x09, 0x22, 0xd3, 0x40, 0x5f, 0xaa, 0x3d, 0x19, 0x4f, 0x82,
182 0xa4, 0x58, 0x30, 0x73, 0x7d, 0x5c, 0xc6, 0xc7, 0x5d, 0x24 };
184 byte[] data = Encoding.Default.GetBytes ("Sample #2");
185 Check ("FIPS198-A2", key, data, fips);
189 public void FIPS198_A3 ()
191 // key > 64 bytes -> requires hashing
192 byte[] key = { 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
193 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
194 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
195 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
196 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
197 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
198 0xb0, 0xb1, 0xb2, 0xb3 };
200 byte[] fips = { 0xbc, 0xf4, 0x1e, 0xab, 0x8b, 0xb2, 0xd8, 0x02, 0xf3, 0xd0,
201 0x5c, 0xaf, 0x7c, 0xb0, 0x92, 0xec, 0xf8, 0xd1, 0xa3, 0xaa };
203 byte[] data = Encoding.Default.GetBytes ("Sample #3");
204 Check ("FIPS198-A3", key, data, fips);
208 public void FIPS198_A4 ()
210 byte[] key = { 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
211 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
212 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d,
213 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
214 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0 };
216 byte[] fips = { 0x9e, 0xa8, 0x86, 0xef, 0xe2, 0x68, 0xdb, 0xec, 0xce, 0x42,
217 0x0c, 0x75, 0x24, 0xdf, 0x32, 0xe0, 0x75, 0x1a, 0x2a, 0x26 };
219 byte[] data = Encoding.Default.GetBytes ("Sample #4");
220 Check ("FIPS198-A4", key, data, fips);
224 public void RFC2202_TC1 ()
226 byte[] key = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b };
227 byte[] data = Encoding.Default.GetBytes ("Hi There");
228 byte[] digest = { 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, 0xf1, 0x46, 0xbe, 0x00 };
229 Check ("RFC2202-TC1", key, data, digest);
233 public void RFC2202_TC2 ()
235 byte[] key = Encoding.Default.GetBytes ("Jefe");
236 byte[] data = Encoding.Default.GetBytes ("what do ya want for nothing?");
237 byte[] digest = { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74, 0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79 };
238 Check ("RFC2202-TC2", key, data, digest);
242 public void RFC2202_TC3 ()
244 byte[] key = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa };
245 byte[] data = new byte [50];
246 for (int i = 0; i < data.Length; i++)
248 byte[] digest = { 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3, 0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1, 0x75, 0xd3 };
249 Check ("RFC2202-TC3", key, data, digest);
253 public void RFC2202_TC4 ()
255 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 };
256 byte[] data = new byte [50];
257 for (int i = 0; i < data.Length; i++)
259 byte[] digest = { 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, 0xbc, 0x84, 0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, 0x2d, 0x72, 0x35, 0xda };
260 Check ("RFC2202-TC4", key, data, digest);
264 public void RFC2202_TC5 ()
266 byte[] key = { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c };
267 byte[] data = Encoding.Default.GetBytes ("Test With Truncation");
268 byte[] digest = { 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2, 0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04 };
269 Check ("RFC2202-TC5", key, data, digest);
273 public void RFC2202_TC6 ()
275 byte[] key = new byte [80];
276 for (int i = 0; i < key.Length; i++)
278 byte[] data = Encoding.Default.GetBytes ("Test Using Larger Than Block-Size Key - Hash Key First");
279 byte[] digest = { 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40, 0x21, 0x12 };
280 Check ("RFC2202-TC6", key, data, digest);
284 public void RFC2202_TC7 ()
286 byte[] key = new byte [80];
287 for (int i = 0; i < key.Length; i++)
289 byte[] data = Encoding.Default.GetBytes ("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data");
290 byte[] digest = { 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91 };
291 Check ("RFC2202-TC7", key, data, digest);