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