Change few Assertions to Asserts
[mono.git] / mcs / class / corlib / Test / System.Security.Cryptography / PaddingModeTest.cs
1 //
2 // PaddingModeTest.cs - NUnit Test Cases for PaddingMode
3 //
4 // Author:
5 //      Sebastien Pouliot (sebastien@ximian.com)
6 //
7 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
8 // Copyright (C) 2004, 2008 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 System;
31 using System.Security.Cryptography;
32
33 using NUnit.Framework;
34
35 namespace MonoTests.System.Security.Cryptography {
36
37         [TestFixture]
38         public class PaddingModeTest {
39
40                 private static byte[] key1 = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
41                 private static byte[] key2 = { 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01 };
42                 private static byte[] key3 = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef };
43
44                 public void AssertEquals (string msg, byte[] array1, byte[] array2) 
45                 {
46                         Assert.AreEqual (array1, array2, msg);
47                 }
48
49                 protected byte[] CombineKeys (byte[] key1, byte[] key2, byte[] key3) 
50                 {
51                         int k1l = key1.Length;
52                         int k2l = key2.Length;
53                         int k3l = key3.Length;
54                         byte[] key = new byte [k1l + k2l + k3l];
55                         Array.Copy (key1, 0, key, 0, k1l);
56                         Array.Copy (key2, 0, key, k1l, k2l);
57                         Array.Copy (key3, 0, key, k1l + k2l, k3l);
58                         return key;
59                 }
60
61                 private byte[] Decrypt (SymmetricAlgorithm algo, PaddingMode padding, byte[] data) 
62                 {
63                         algo.IV = new byte [algo.BlockSize >> 3];
64                         algo.Mode = CipherMode.CBC;
65                         algo.Padding = padding;
66                         ICryptoTransform ct = algo.CreateDecryptor ();
67                         return ct.TransformFinalBlock (data, 0, data.Length);
68                 }
69
70                 private byte[] Encrypt (SymmetricAlgorithm algo, PaddingMode padding, byte[] data) 
71                 {
72                         algo.IV = new byte [algo.BlockSize >> 3];
73                         algo.Mode = CipherMode.CBC;
74                         algo.Padding = padding;
75                         ICryptoTransform ct = algo.CreateEncryptor ();
76                         return ct.TransformFinalBlock (data, 0, data.Length);
77                 }
78
79                 private byte[] GetData (byte size) 
80                 {
81                         byte[] data = new byte [size];
82                         for (byte i=0; i < size; i++) {
83                                 data [i] = i;
84                         }
85                         return data;
86                 }
87
88                 private TripleDES GetTripleDES () 
89                 {
90                         TripleDES tdes = TripleDES.Create ();
91                         tdes.Key = CombineKeys (key1, key2, key3);
92                         return tdes;
93                 }
94
95                 [Test]
96                 [ExpectedException (typeof (CryptographicException))]
97                 public void TripleDESNone_SmallerThanOneBlockSize () 
98                 {
99                         TripleDES tdes = GetTripleDES ();
100                         byte[] data = GetData (7);
101                         byte[] encdata = Encrypt (tdes, PaddingMode.None, data);
102                 }
103
104                 [Test]
105                 public void TripleDESNone_ExactlyOneBlockSize () 
106                 {
107                         TripleDES tdes = GetTripleDES ();
108                         byte[] data = GetData (8);
109                         byte[] encdata = Encrypt (tdes, PaddingMode.None, data);
110                         Assert.AreEqual ("23-61-AC-E6-C5-17-10-51", BitConverter.ToString (encdata), "TripleDESNone_ExactlyOneBlockSize_Encrypt");
111                         byte[] decdata = Decrypt (tdes, PaddingMode.None, encdata);
112                         AssertEquals ("TripleDESNone_ExactlyOneBlockSize_Decrypt", data, decdata);
113                 }
114
115                 [Test]
116                 [ExpectedException (typeof (CryptographicException))]
117                 public void TripleDESNone_MoreThanOneBlockSize () 
118                 {
119                         TripleDES tdes = GetTripleDES ();
120                         byte[] data = GetData (12);
121                         byte[] encdata = Encrypt (tdes, PaddingMode.None, data);
122                 }
123
124                 [Test]
125                 public void TripleDESNone_ExactMultipleBlockSize () 
126                 {
127                         TripleDES tdes = GetTripleDES ();
128                         byte[] data = GetData (48);
129                         byte[] encdata = Encrypt (tdes, PaddingMode.None, data);
130                         // note: encrypted data is truncated to a multiple of block size
131                         Assert.AreEqual ("23-61-AC-E6-C5-17-10-51-BF-AB-79-9C-CD-5E-79-40-16-81-0D-6B-40-E6-B2-E9-86-34-8A-9E-5D-56-DA-D1-0C-8C-76-0A-E1-69-A1-0A-B5-B5-7F-FC-5A-D0-6E-6A", BitConverter.ToString (encdata), "TripleDESNone_ExactMultipleBlockSize_Encrypt");
132                         byte[] decdata = Decrypt (tdes, PaddingMode.None, encdata);
133                         AssertEquals ("TripleDESNone_ExactMultipleBlockSize_Decrypt", GetData (48), decdata);
134                 }
135
136                 [Test]
137                 public void TripleDESPKCS7_SmallerThanOneBlockSize () 
138                 {
139                         TripleDES tdes = GetTripleDES ();
140                         byte[] data = GetData (7);
141                         byte[] encdata = Encrypt (tdes, PaddingMode.PKCS7, data);
142                         Assert.AreEqual ("C6-59-0E-E3-7F-26-92-B0", BitConverter.ToString (encdata), "TripleDESPKCS7_SmallerThanOneBlockSize_Encrypt");
143                         byte[] decdata = Decrypt (tdes, PaddingMode.PKCS7, encdata);
144                         AssertEquals ("TripleDESPKCS7_SmallerThanOneBlockSize_Decrypt", data, decdata);
145                 }
146
147                 [Test]
148                 public void TripleDESPKCS7_ExactlyOneBlockSize () 
149                 {
150                         TripleDES tdes = GetTripleDES ();
151                         byte[] data = GetData (8);
152                         byte[] encdata = Encrypt (tdes, PaddingMode.PKCS7, data);
153                         Assert.AreEqual ("23-61-AC-E6-C5-17-10-51-C0-60-5B-6A-5C-B7-69-62", BitConverter.ToString (encdata), "TripleDESPKCS7_ExactlyOneBlockSize_Encrypt");
154                         byte[] decdata = Decrypt (tdes, PaddingMode.PKCS7, encdata);
155                         AssertEquals ("TripleDESPKCS7_ExactlyOneBlockSize_Decrypt", data, decdata);
156                 }
157
158                 [Test]
159                 public void TripleDESPKCS7_MoreThanOneBlockSize () 
160                 {
161                         TripleDES tdes = GetTripleDES ();
162                         byte[] data = GetData (12);
163                         byte[] encdata = Encrypt (tdes, PaddingMode.PKCS7, data);
164                         Assert.AreEqual ("23-61-AC-E6-C5-17-10-51-D9-CB-92-8C-76-89-35-84", BitConverter.ToString (encdata), "TripleDESPKCS7_MoreThanOneBlockSize_Encrypt");
165                         byte[] decdata = Decrypt (tdes, PaddingMode.PKCS7, encdata);
166                         AssertEquals ("TripleDESPKCS7_MoreThanOneBlockSize_Decrypt", data, decdata);
167                 }
168
169                 [Test]
170                 public void TripleDESPKCS7_ExactMultipleBlockSize () 
171                 {
172                         TripleDES tdes = GetTripleDES ();
173                         byte[] data = GetData (48);
174                         byte[] encdata = Encrypt (tdes, PaddingMode.PKCS7, data);
175                         Assert.AreEqual ("23-61-AC-E6-C5-17-10-51-BF-AB-79-9C-CD-5E-79-40-16-81-0D-6B-40-E6-B2-E9-86-34-8A-9E-5D-56-DA-D1-0C-8C-76-0A-E1-69-A1-0A-B5-B5-7F-FC-5A-D0-6E-6A-73-61-63-1C-58-A2-9C-B3", BitConverter.ToString (encdata), "TripleDESPKCS7_ExactMultipleBlockSize_Encrypt");
176                         byte[] decdata = Decrypt (tdes, PaddingMode.PKCS7, encdata);
177                         AssertEquals ("TripleDESPKCS7_ExactMultipleBlockSize_Decrypt", data, decdata);
178                 }
179                 
180                 [Test]
181                 public void TripleDESZeros_SmallerThanOneBlockSize () 
182                 {
183                         TripleDES tdes = GetTripleDES ();
184                         byte[] data = GetData (7);
185                         byte[] encdata = Encrypt (tdes, PaddingMode.Zeros, data);
186                         Assert.AreEqual ("B8-5C-5B-A5-06-0B-7E-C6", BitConverter.ToString (encdata), "TripleDESZeros_SmallerThanOneBlockSize_Encrypt");
187                         byte[] decdata = Decrypt (tdes, PaddingMode.Zeros, encdata);
188                         Assert.AreEqual ("00-01-02-03-04-05-06-00", BitConverter.ToString (decdata), "TripleDESZeros_SmallerThanOneBlockSize_Decrypt");
189                 }
190
191                 [Test]
192                 public void TripleDESZeros_ExactlyOneBlockSize () 
193                 {
194                         TripleDES tdes = GetTripleDES ();
195                         byte[] data = GetData (8);
196                         byte[] encdata = Encrypt (tdes, PaddingMode.Zeros, data);
197                         Assert.AreEqual ("23-61-AC-E6-C5-17-10-51", BitConverter.ToString (encdata), "TripleDESZeros_ExactlyOneBlockSize_Encrypt");
198                         byte[] decdata = Decrypt (tdes, PaddingMode.Zeros, encdata);
199                         AssertEquals ("TripleDESZeros_ExactlyOneBlockSize_Decrypt", data, decdata);
200                 }
201
202                 [Test]
203                 public void TripleDESZeros_MoreThanOneBlockSize () 
204                 {
205                         TripleDES tdes = GetTripleDES ();
206                         byte[] data = GetData (12);
207                         byte[] encdata = Encrypt (tdes, PaddingMode.Zeros, data);
208                         Assert.AreEqual ("23-61-AC-E6-C5-17-10-51-6E-75-2E-33-12-09-5D-66", BitConverter.ToString (encdata), "TripleDESZeros_MoreThanOneBlockSize_Encrypt");
209                         byte[] decdata = Decrypt (tdes, PaddingMode.Zeros, encdata);
210                         Assert.AreEqual ("00-01-02-03-04-05-06-07-08-09-0A-0B-00-00-00-00", BitConverter.ToString (decdata), "TripleDESZeros_MoreThanOneBlockSize_Decrypt");
211                 }
212
213                 [Test]
214                 public void TripleDESZeros_ExactMultipleBlockSize () 
215                 {
216                         TripleDES tdes = GetTripleDES ();
217                         byte[] data = GetData (48);
218                         byte[] encdata = Encrypt (tdes, PaddingMode.Zeros, data);
219                         Assert.AreEqual ("23-61-AC-E6-C5-17-10-51-BF-AB-79-9C-CD-5E-79-40-16-81-0D-6B-40-E6-B2-E9-86-34-8A-9E-5D-56-DA-D1-0C-8C-76-0A-E1-69-A1-0A-B5-B5-7F-FC-5A-D0-6E-6A", BitConverter.ToString (encdata), "TripleDESZeros_ExactMultipleBlockSize_Encrypt");
220                         byte[] decdata = Decrypt (tdes, PaddingMode.Zeros, encdata);
221                         AssertEquals ("TripleDESZeros_ExactMultipleBlockSize_Decrypt", GetData (48), decdata);
222                 }
223
224                 private Rijndael GetAES () 
225                 {
226                         Rijndael aes = Rijndael.Create ();
227                         aes.Key = CombineKeys (key1, key2, key3);
228                         return aes;
229                 }
230
231                 [Test]
232                 [ExpectedException (typeof (CryptographicException))]
233                 public void RijndaelNone_SmallerThanOneBlockSize () 
234                 {
235                         Rijndael aes = GetAES ();
236                         byte[] data = GetData (8);
237                         byte[] encdata = Encrypt (aes, PaddingMode.None, data);
238                 }
239
240                 [Test]
241                 public void RijndaelNone_ExactlyOneBlockSize () 
242                 {
243                         Rijndael aes = GetAES ();
244                         byte[] data = GetData (16);
245                         byte[] encdata = Encrypt (aes, PaddingMode.None, data);
246                         Assert.AreEqual ("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB", BitConverter.ToString (encdata), "RijndaelNone_ExactlyOneBlockSize_Encrypt");
247                         byte[] decdata = Decrypt (aes, PaddingMode.None, encdata);
248                         AssertEquals ("RijndaelNone_ExactlyOneBlockSize_Decrypt", data, decdata);
249                 }
250
251                 [Test]
252                 [ExpectedException (typeof (CryptographicException))]
253                 public void RijndaelNone_MoreThanOneBlockSize () 
254                 {
255                         Rijndael aes = GetAES ();
256                         byte[] data = GetData (20);
257                         byte[] encdata = Encrypt (aes, PaddingMode.None, data);
258                 }
259
260                 [Test]
261                 public void RijndaelNone_ExactMultipleBlockSize () 
262                 {
263                         Rijndael aes = GetAES ();
264                         byte[] data = GetData (48);
265                         byte[] encdata = Encrypt (aes, PaddingMode.None, data);
266                         // note: encrypted data is truncated to a multiple of block size
267                         Assert.AreEqual ("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB-E1-27-3E-21-5A-BE-D5-12-F4-AF-06-8D-0A-BD-02-64-02-CB-FF-D7-32-19-5E-69-3C-54-C2-8C-A1-D7-72-FF", BitConverter.ToString (encdata), "RijndaelNone_ExactMultipleBlockSize_Encrypt");
268                         byte[] decdata = Decrypt (aes, PaddingMode.None, encdata);
269                         AssertEquals ("RijndaelNone_ExactMultipleBlockSize_Decrypt", GetData (48), decdata);
270                 }
271
272                 [Test]
273                 public void RijndaelPKCS7_SmallerThanOneBlockSize () 
274                 {
275                         Rijndael aes = GetAES ();
276                         byte[] data = GetData (8);
277                         byte[] encdata = Encrypt (aes, PaddingMode.PKCS7, data);
278                         Assert.AreEqual ("AB-E0-20-5E-BC-28-A0-B7-A7-56-A3-BF-13-55-13-7E", BitConverter.ToString (encdata), "RijndaelPKCS7_SmallerThanOneBlockSize_Encrypt");
279                         byte[] decdata = Decrypt (aes, PaddingMode.PKCS7, encdata);
280                         AssertEquals ("RijndaelPKCS7_SmallerThanOneBlockSize_Decrypt", data, decdata);
281                 }
282
283                 [Test]
284                 public void RijndaelPKCS7_ExactlyOneBlockSize () 
285                 {
286                         Rijndael aes = GetAES ();
287                         byte[] data = GetData (16);
288                         byte[] encdata = Encrypt (aes, PaddingMode.PKCS7, data);
289                         Assert.AreEqual ("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB-60-CE-9F-E0-72-3B-D6-D1-A5-F8-33-D8-25-31-7F-D4", BitConverter.ToString (encdata), "RijndaelPKCS7_ExactlyOneBlockSize_Encrypt");
290                         byte[] decdata = Decrypt (aes, PaddingMode.PKCS7, encdata);
291                         AssertEquals ("RijndaelPKCS7_ExactlyOneBlockSize_Decrypt", data, decdata);
292                 }
293
294                 [Test]
295                 public void RijndaelPKCS7_MoreThanOneBlockSize () 
296                 {
297                         Rijndael aes = GetAES ();
298                         byte[] data = GetData (20);
299                         byte[] encdata = Encrypt (aes, PaddingMode.PKCS7, data);
300                         Assert.AreEqual ("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB-06-3F-D3-51-8D-55-E9-2F-02-4A-4E-F2-91-55-31-83", BitConverter.ToString (encdata), "RijndaelPKCS7_MoreThanOneBlockSize_Encrypt");
301                         byte[] decdata = Decrypt (aes, PaddingMode.PKCS7, encdata);
302                         AssertEquals ("RijndaelPKCS7_MoreThanOneBlockSize_Decrypt", data, decdata);
303                 }
304
305                 [Test]
306                 public void RijndaelPKCS7_ExactMultipleBlockSize () 
307                 {
308                         Rijndael aes = GetAES ();
309                         byte[] data = GetData (48);
310                         byte[] encdata = Encrypt (aes, PaddingMode.PKCS7, data);
311                         Assert.AreEqual ("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB-E1-27-3E-21-5A-BE-D5-12-F4-AF-06-8D-0A-BD-02-64-02-CB-FF-D7-32-19-5E-69-3C-54-C2-8C-A1-D7-72-FF-37-42-81-21-47-A7-E0-AA-64-A7-8B-65-25-95-AA-54", BitConverter.ToString (encdata), "RijndaelPKCS7_ExactMultipleBlockSize_Encrypt");
312                         byte[] decdata = Decrypt (aes, PaddingMode.PKCS7, encdata);
313                         AssertEquals ("RijndaelPKCS7_ExactMultipleBlockSize_Decrypt", data, decdata);
314                 }
315                 
316                 [Test]
317                 public void RijndaelZeros_SmallerThanOneBlockSize () 
318                 {
319                         Rijndael aes = GetAES ();
320                         byte[] data = GetData (8);
321                         byte[] encdata = Encrypt (aes, PaddingMode.Zeros, data);
322                         Assert.AreEqual ("DD-BE-D7-CE-E2-DD-5C-A3-3E-44-A1-76-00-E5-5B-5D", BitConverter.ToString (encdata), "RijndaelZeros_SmallerThanOneBlockSize_Encrypt");
323                         byte[] decdata = Decrypt (aes, PaddingMode.Zeros, encdata);
324                         Assert.AreEqual ("00-01-02-03-04-05-06-07-00-00-00-00-00-00-00-00", BitConverter.ToString (decdata), "RijndaelZeros_SmallerThanOneBlockSize_Decrypt");
325                 }
326
327                 [Test]
328                 public void RijndaelZeros_ExactlyOneBlockSize () 
329                 {
330                         Rijndael aes = GetAES ();
331                         byte[] data = GetData (16);
332                         byte[] encdata = Encrypt (aes, PaddingMode.Zeros, data);
333                         Assert.AreEqual ("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB", BitConverter.ToString (encdata), "RijndaelZeros_ExactlyOneBlockSize_Encrypt");
334                         byte[] decdata = Decrypt (aes, PaddingMode.Zeros, encdata);
335                         AssertEquals ("RijndaelZeros_ExactlyOneBlockSize_Decrypt", data, decdata);
336                 }
337
338                 [Test]
339                 public void RijndaelZeros_MoreThanOneBlockSize () 
340                 {
341                         Rijndael aes = GetAES ();
342                         byte[] data = GetData (20);
343                         byte[] encdata = Encrypt (aes, PaddingMode.Zeros, data);
344                         Assert.AreEqual ("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB-04-6C-F7-A5-DE-FF-B4-30-29-7A-0E-04-3B-D4-B8-F2", BitConverter.ToString (encdata), "RijndaelZeros_MoreThanOneBlockSize_Encrypt");
345                         byte[] decdata = Decrypt (aes, PaddingMode.Zeros, encdata);
346                         Assert.AreEqual ("00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F-10-11-12-13-00-00-00-00-00-00-00-00-00-00-00-00", BitConverter.ToString (decdata), "RijndaelZeros_MoreThanOneBlockSize_Decrypt");
347                 }
348
349                 [Test]
350                 public void RijndaelZeros_ExactMultipleBlockSize () 
351                 {
352                         Rijndael aes = GetAES ();
353                         byte[] data = GetData (48);
354                         byte[] encdata = Encrypt (aes, PaddingMode.Zeros, data);
355                         Assert.AreEqual ("79-42-36-2F-D6-DB-F1-0C-87-99-58-06-D5-F6-B0-BB-E1-27-3E-21-5A-BE-D5-12-F4-AF-06-8D-0A-BD-02-64-02-CB-FF-D7-32-19-5E-69-3C-54-C2-8C-A1-D7-72-FF", BitConverter.ToString (encdata), "RijndaelZeros_ExactMultipleBlockSize_Encrypt");
356                         byte[] decdata = Decrypt (aes, PaddingMode.Zeros, encdata);
357                         AssertEquals ("RijndaelZeros_ExactMultipleBlockSize_Decrypt", GetData (48), decdata);
358                 }
359
360                 // Enum tests
361
362                 [Test]
363                 public void PaddingModeEnum ()
364                 {
365 #if NET_2_0
366                         Assert.AreEqual (4, (int)PaddingMode.ANSIX923, "ANSIX923");
367                         Assert.AreEqual (5, (int)PaddingMode.ISO10126, "ISO10126");
368 #endif
369                         Assert.AreEqual (1, (int)PaddingMode.None, "None");
370                         Assert.AreEqual (2, (int)PaddingMode.PKCS7, "PKCS7");
371                         Assert.AreEqual (3, (int)PaddingMode.Zeros, "Zeros");
372                 }
373
374                 // SymmetricAlgorithm tests
375
376                 private byte[] GetKey (SymmetricAlgorithm sa) 
377                 {
378                         byte[] key = new byte [sa.KeySize >> 3];
379                         // no weak key this way (DES, TripleDES)
380                         for (byte i=0; i < key.Length; i++)
381                                 key [i] = i;
382                         return key;
383                 }
384
385                 private byte[] GetIV (SymmetricAlgorithm sa)
386                 {
387                         return new byte [sa.BlockSize >> 3];
388                 }
389
390                 private ICryptoTransform GetEncryptor (SymmetricAlgorithm sa, PaddingMode mode) 
391                 {
392                         sa.Mode = CipherMode.ECB; // basic (no) mode
393                         sa.Padding = mode;
394                         return sa.CreateEncryptor (GetKey (sa), GetIV (sa));
395                 }
396
397                 private ICryptoTransform GetDecryptor (SymmetricAlgorithm sa, PaddingMode mode)
398                 {
399                         sa.Mode = CipherMode.ECB; // basic (no) mode
400                         sa.Padding = mode;
401                         return sa.CreateDecryptor (GetKey (sa), GetIV (sa));
402                 }
403
404                 // the best way to verify padding is to:
405                 // a. encrypt data larger than one block with a padding mode "X"
406                 // b. decrypt the data with padding mode "None"
407                 // c. compare the last (padding) bytes with the expected padding
408 #if NET_2_0
409                 private void ANSIX923_Full (SymmetricAlgorithm sa)
410                 {
411                         int bs = (sa.BlockSize >> 3);
412                         // one full block
413                         byte[] data = new byte [bs]; // in bytes
414                         ICryptoTransform enc = GetEncryptor (sa, PaddingMode.ANSIX923);
415                         byte[] encdata = enc.TransformFinalBlock (data, 0, data.Length);
416                         // one block of padding is added                        
417                         Assert.AreEqual (data.Length * 2, encdata.Length, "one more block added");
418
419                         ICryptoTransform dec = GetDecryptor (sa, PaddingMode.None);
420                         byte[] decdata = dec.TransformFinalBlock (encdata, 0, encdata.Length);
421                         Assert.AreEqual (encdata.Length, decdata.Length, "no unpadding");
422
423                         int pd = decdata.Length - data.Length;
424                         // now validate padding - ANSI X.923 is all 0 except last byte (length)
425                         for (int i=0; i < bs - 1; i++)
426                                 Assert.AreEqual (0x00, decdata [decdata.Length - pd + i], i.ToString ());
427                         Assert.AreEqual (pd, decdata [decdata.Length - 1], "last byte");
428                 }
429
430                 private void ANSIX923_Partial (SymmetricAlgorithm sa)
431                 {
432                         int bs = (sa.BlockSize >> 3);
433                         // one and an half block
434                         byte[] data = new byte [bs + (bs >> 1)]; // in bytes
435                         ICryptoTransform enc = GetEncryptor (sa, PaddingMode.ANSIX923);
436                         byte[] encdata = enc.TransformFinalBlock (data, 0, data.Length);
437                         // one block of padding is added                        
438                         Assert.AreEqual (bs * 2, encdata.Length, "one more block added");
439
440                         ICryptoTransform dec = GetDecryptor (sa, PaddingMode.None);
441                         byte[] decdata = dec.TransformFinalBlock (encdata, 0, encdata.Length);
442                         Assert.AreEqual (encdata.Length, decdata.Length, "no unpadding");
443
444                         int pd = decdata.Length - data.Length;
445                         // now validate padding - ANSI X.923 is all 0 except last byte (length)
446                         for (int i = 0; i < pd - 1; i++)
447                                 Assert.AreEqual (0x00, decdata [decdata.Length - pd + i], i.ToString ());
448                         Assert.AreEqual (pd, decdata [decdata.Length - 1], "last byte");
449                 }
450
451                 private void ISO10126_Full (SymmetricAlgorithm sa)
452                 {
453                         int bs = (sa.BlockSize >> 3);
454                         // one full block
455                         byte [] data = new byte [bs]; // in bytes
456                         ICryptoTransform enc = GetEncryptor (sa, PaddingMode.ISO10126);
457                         byte [] encdata = enc.TransformFinalBlock (data, 0, data.Length);
458                         // one block of padding is added                        
459                         Assert.AreEqual (data.Length * 2, encdata.Length, "one more block added");
460
461                         ICryptoTransform dec = GetDecryptor (sa, PaddingMode.None);
462                         byte [] decdata = dec.TransformFinalBlock (encdata, 0, encdata.Length);
463                         Assert.AreEqual (encdata.Length, decdata.Length, "no unpadding");
464
465                         int pd = decdata.Length - data.Length;
466                         // now validate padding - ISO10126 is all random except last byte (length)
467                         Assert.AreEqual (pd, decdata [decdata.Length - 1], "last byte");
468                 }
469
470                 private void ISO10126_Partial (SymmetricAlgorithm sa)
471                 {
472                         int bs = (sa.BlockSize >> 3);
473                         // one and an half block
474                         byte [] data = new byte [bs + (bs >> 1)]; // in bytes
475                         ICryptoTransform enc = GetEncryptor (sa, PaddingMode.ISO10126);
476                         byte [] encdata = enc.TransformFinalBlock (data, 0, data.Length);
477                         // one block of padding is added                        
478                         Assert.AreEqual (bs * 2, encdata.Length, "one more block added");
479
480                         ICryptoTransform dec = GetDecryptor (sa, PaddingMode.None);
481                         byte [] decdata = dec.TransformFinalBlock (encdata, 0, encdata.Length);
482                         Assert.AreEqual (encdata.Length, decdata.Length, "no unpadding");
483
484                         int pd = decdata.Length - data.Length;
485                         // now validate padding - ISO10126 is all random except last byte (length)
486                         Assert.AreEqual (pd, decdata [decdata.Length - 1], "last byte");
487                 }
488 #endif
489                 private void PKCS7_Full (SymmetricAlgorithm sa)
490                 {
491                         int bs = (sa.BlockSize >> 3);
492                         // one full block
493                         byte[] data = new byte [bs]; // in bytes
494                         ICryptoTransform enc = GetEncryptor (sa, PaddingMode.PKCS7);
495                         byte[] encdata = enc.TransformFinalBlock (data, 0, data.Length);
496                         // one block of padding is added                        
497                         Assert.AreEqual (data.Length * 2, encdata.Length, "one more block added");
498
499                         ICryptoTransform dec = GetDecryptor (sa, PaddingMode.None);
500                         byte[] decdata = dec.TransformFinalBlock (encdata, 0, encdata.Length);
501                         Assert.AreEqual (encdata.Length, decdata.Length, "no unpadding");
502
503                         int pd = decdata.Length - data.Length;
504                         // now validate padding - PKCS7 is all padding char
505                         for (int i = 0; i < bs; i++)
506                                 Assert.AreEqual (pd, decdata [decdata.Length - pd + i], i.ToString ());
507                 }
508
509                 private void PKCS7_Partial (SymmetricAlgorithm sa)
510                 {
511                         int bs = (sa.BlockSize >> 3);
512                         // one and an half block
513                         byte[] data = new byte[bs + (bs >> 1)]; // in bytes
514                         ICryptoTransform enc = GetEncryptor (sa, PaddingMode.PKCS7);
515                         byte[] encdata = enc.TransformFinalBlock (data, 0, data.Length);
516                         // one block of padding is added                        
517                         Assert.AreEqual (bs * 2, encdata.Length, "one more block added");
518
519                         ICryptoTransform dec = GetDecryptor (sa, PaddingMode.None);
520                         byte[] decdata = dec.TransformFinalBlock (encdata, 0, encdata.Length);
521                         Assert.AreEqual (encdata.Length, decdata.Length, "no unpadding");
522
523                         int pd = decdata.Length - data.Length;
524                         // now validate padding - PKCS7 is all padding char
525                         for (int i = 0; i < pd; i++)
526                                 Assert.AreEqual (pd, decdata [decdata.Length - pd + i], i.ToString ());
527                 }
528
529                 private void Zeros_Full (SymmetricAlgorithm sa)
530                 {
531                         int bs = (sa.BlockSize >> 3);
532                         // one full block
533                         byte [] data = new byte [bs]; // in bytes
534                         for (int i = 0; i < data.Length; i++)
535                                 data [i] = 0xFF;
536
537                         ICryptoTransform enc = GetEncryptor (sa, PaddingMode.Zeros);
538                         byte [] encdata = enc.TransformFinalBlock (data, 0, data.Length);
539                         // NO extra block is used for zero padding
540                         Assert.AreEqual (data.Length, encdata.Length, "no extra block added");
541
542                         ICryptoTransform dec = GetDecryptor (sa, PaddingMode.None);
543                         byte [] decdata = dec.TransformFinalBlock (encdata, 0, encdata.Length);
544                         Assert.AreEqual (encdata.Length, decdata.Length, "no unpadding");
545
546                         // now validate absence of padding
547                         Assert.AreEqual (0xFF, decdata [decdata.Length - 1], "no padding");
548                 }
549
550                 private void Zeros_Partial (SymmetricAlgorithm sa)
551                 {
552                         int bs = (sa.BlockSize >> 3);
553                         // one and an half block
554                         byte [] data = new byte [bs + (bs >> 1)]; // in bytes
555                         for (int i=0; i < data.Length; i++)
556                                 data [i] = 0xFF;
557
558                         ICryptoTransform enc = GetEncryptor (sa, PaddingMode.Zeros);
559                         byte [] encdata = enc.TransformFinalBlock (data, 0, data.Length);
560                         // one block of padding is added                        
561                         Assert.AreEqual (bs * 2, encdata.Length, "one more block added");
562
563                         ICryptoTransform dec = GetDecryptor (sa, PaddingMode.None);
564                         byte [] decdata = dec.TransformFinalBlock (encdata, 0, encdata.Length);
565                         Assert.AreEqual (encdata.Length, decdata.Length, "no unpadding");
566
567                         int pd = decdata.Length - data.Length;
568                         // now validate padding - Zeros is all 0x00 char
569                         for (int i = 0; i < pd; i++)
570                                 Assert.AreEqual (0x00, decdata [decdata.Length - pd + i], i.ToString ());
571                 }
572 #if NET_2_0
573                 // ANSI X.923
574
575                 [Test]
576                 public void DES_ANSIX923_Full ()
577                 {
578                         ANSIX923_Full (DES.Create ());
579                 }
580
581                 [Test]
582                 public void DES_ANSIX923_Partial ()
583                 {
584                         ANSIX923_Partial (DES.Create ());
585                 }
586
587                 [Test]
588                 public void RC2_ANSIX923_Full ()
589                 {
590                         ANSIX923_Full (RC2.Create ());
591                 }
592
593                 [Test]
594                 public void RC2_ANSIX923_Partial ()
595                 {
596                         ANSIX923_Partial (RC2.Create ());
597                 }
598
599                 [Test]
600                 public void Rijndael_ANSIX923_Full () 
601                 {
602                         ANSIX923_Full (Rijndael.Create ());
603                 }
604
605                 [Test]
606                 public void Rijndael_ANSIX923_Partial ()
607                 {
608                         ANSIX923_Partial (Rijndael.Create ());
609                 }
610
611                 [Test]
612                 public void TripleDES_ANSIX923_Full ()
613                 {
614                         ANSIX923_Full (TripleDES.Create ());
615                 }
616
617                 [Test]
618                 public void TripleDES_ANSIX923_Partial ()
619                 {
620                         ANSIX923_Partial (TripleDES.Create ());
621                 }
622
623                 // ISO 10126
624
625                 [Test]
626                 public void DES_ISO10126_Full ()
627                 {
628                         ISO10126_Full (DES.Create ());
629                 }
630
631                 [Test]
632                 public void DES_ISO10126_Partial ()
633                 {
634                         ISO10126_Partial (DES.Create ());
635                 }
636
637                 [Test]
638                 public void RC2_ISO10126_Full ()
639                 {
640                         ISO10126_Full (RC2.Create ());
641                 }
642
643                 [Test]
644                 public void RC2_ISO10126_Partial ()
645                 {
646                         ISO10126_Partial (RC2.Create ());
647                 }
648
649                 [Test]
650                 public void Rijndael_ISO10126_Full ()
651                 {
652                         ISO10126_Full (Rijndael.Create ());
653                 }
654
655                 [Test]
656                 public void Rijndael_ISO10126_Partial ()
657                 {
658                         ISO10126_Partial (Rijndael.Create ());
659                 }
660
661                 [Test]
662                 public void TripleDES_ISO10126_Full ()
663                 {
664                         ISO10126_Full (TripleDES.Create ());
665                 }
666
667                 [Test]
668                 public void TripleDES_ISO10126_Partial ()
669                 {
670                         ISO10126_Partial (TripleDES.Create ());
671                 }
672 #endif
673                 // PKCS #7
674
675                 [Test]
676                 public void DES_PKCS7_Full ()
677                 {
678                         PKCS7_Full (DES.Create ());
679                 }
680
681                 [Test]
682                 public void DES_PKCS7_Partial ()
683                 {
684                         PKCS7_Partial (DES.Create ());
685                 }
686
687                 [Test]
688                 public void RC2_PKCS7_Full ()
689                 {
690                         PKCS7_Full (RC2.Create ());
691                 }
692
693                 [Test]
694                 public void RC2_PKCS7_Partial ()
695                 {
696                         PKCS7_Partial (RC2.Create ());
697                 }
698
699                 [Test]
700                 public void Rijndael_PKCS7_Full ()
701                 {
702                         PKCS7_Full (Rijndael.Create ());
703                 }
704
705                 [Test]
706                 public void Rijndael_PKCS7_Partial ()
707                 {
708                         PKCS7_Partial (Rijndael.Create ());
709                 }
710
711                 [Test]
712                 public void TripleDES_PKCS7_Full ()
713                 {
714                         PKCS7_Full (TripleDES.Create ());
715                 }
716
717                 [Test]
718                 public void TripleDES_PKCS7_Partial ()
719                 {
720                         PKCS7_Partial (TripleDES.Create ());
721                 }
722
723                 // Zeros
724
725                 [Test]
726                 public void DES_Zeros_Full ()
727                 {
728                         Zeros_Full (DES.Create ());
729                 }
730
731                 [Test]
732                 public void DES_Zeros_Partial ()
733                 {
734                         Zeros_Partial (DES.Create ());
735                 }
736
737                 [Test]
738                 public void RC2_Zeros_Full ()
739                 {
740                         Zeros_Full (RC2.Create ());
741                 }
742
743                 [Test]
744                 public void RC2_Zeros_Partial ()
745                 {
746                         Zeros_Partial (RC2.Create ());
747                 }
748
749                 [Test]
750                 public void Rijndael_Zeros_Full ()
751                 {
752                         Zeros_Full (Rijndael.Create ());
753                 }
754
755                 [Test]
756                 public void Rijndael_Zeros_Partial ()
757                 {
758                         Zeros_Partial (Rijndael.Create ());
759                 }
760
761                 [Test]
762                 public void TripleDES_Zeros_Full ()
763                 {
764                         Zeros_Full (TripleDES.Create ());
765                 }
766
767                 [Test]
768                 public void TripleDES_Zeros_Partial ()
769                 {
770                         Zeros_Partial (TripleDES.Create ());
771                 }
772
773                 // Padding mismatches
774
775                 // the best way to test bad padding is to:
776                 // a. encrypt data larger than one block with a padding mode "X"
777                 // b. decrypt the data with padding mode "Y" (different with Y)
778                 // c. check if the "bad" padding was removed correctly
779                 //
780                 // returns (bitmask)
781                 // 1 - length difference
782                 // 2 - original data lost
783                 // 4 - CryptographicException thrown while decryption
784                 private int Mismatch (PaddingMode encrypt, PaddingMode decrypt)
785                 {
786                         SymmetricAlgorithm sa = SymmetricAlgorithm.Create ();
787                         int bs = (sa.BlockSize >> 3);
788                         // one full block
789                         byte [] data = new byte [bs]; // in bytes
790                         ICryptoTransform enc = GetEncryptor (sa, encrypt);
791                         byte [] encdata = enc.TransformFinalBlock (data, 0, data.Length);
792
793                         int result = 0;
794                         try {
795                                 ICryptoTransform dec = GetDecryptor (sa, decrypt);
796                                 byte [] decdata = dec.TransformFinalBlock (encdata, 0, encdata.Length);
797                                 
798                                 if (data.Length != decdata.Length)
799                                         result += 1;
800
801                                 for (int i=0; i < data.Length; i++) {
802                                         if (data [i] != decdata [i]) {
803                                                 result += 2;
804                                                 break;
805                                         }
806                                 }
807                         }
808                         catch (CryptographicException) {
809                                 result += 4;
810                         }
811                         return result;
812                 }
813 #if NET_2_0
814                 [Test]
815                 public void ANSIX923_ISO10126 () 
816                 {
817                         Assert.AreEqual (0, Mismatch (PaddingMode.ANSIX923, PaddingMode.ISO10126));
818                 }
819
820                 [Test]
821                 public void ANSIX923_None ()
822                 {
823                         Assert.AreEqual (1, Mismatch (PaddingMode.ANSIX923, PaddingMode.None));
824                 }
825
826                 [Test]
827                 public void ANSIX923_PKCS7 ()
828                 {
829                         Assert.AreEqual (4, Mismatch (PaddingMode.ANSIX923, PaddingMode.PKCS7));
830                 }
831
832                 [Test]
833                 public void ANSIX923_Zeros ()
834                 {
835                         Assert.AreEqual (1, Mismatch (PaddingMode.ANSIX923, PaddingMode.Zeros));
836                 }
837
838                 [Test]
839                 public void ISO10126_ANSIX923 ()
840                 {
841                         Assert.AreEqual (4, Mismatch (PaddingMode.ISO10126, PaddingMode.ANSIX923));
842                 }
843
844                 [Test]
845                 public void ISO10126_None ()
846                 {
847                         Assert.AreEqual (1, Mismatch (PaddingMode.ISO10126, PaddingMode.None));
848                 }
849
850                 [Test]
851                 public void ISO10126_PKCS7 ()
852                 {
853                         Assert.AreEqual (4, Mismatch (PaddingMode.ISO10126, PaddingMode.PKCS7));
854                 }
855
856                 [Test]
857                 public void ISO10126_Zeros ()
858                 {
859                         Assert.AreEqual (1, Mismatch (PaddingMode.ISO10126, PaddingMode.Zeros));
860                 }
861
862                 [Test]
863                 public void None_ANSIX923 ()
864                 {
865                         Assert.AreEqual (4, Mismatch (PaddingMode.None, PaddingMode.ANSIX923));
866                 }
867
868                 [Test]
869                 public void None_ISO10126 ()
870                 {
871                         Assert.AreEqual (4, Mismatch (PaddingMode.None, PaddingMode.ISO10126));
872                 }
873 #endif
874                 [Test]
875                 public void None_PKCS7 ()
876                 {
877 #if NET_2_0
878                         Assert.AreEqual (4, Mismatch (PaddingMode.None, PaddingMode.PKCS7));
879 #else
880                         Assert.AreEqual (0, Mismatch (PaddingMode.None, PaddingMode.PKCS7));
881 #endif
882                 }
883
884                 [Test]
885                 public void None_Zeros ()
886                 {
887                         Assert.AreEqual (0, Mismatch (PaddingMode.None, PaddingMode.Zeros));
888                 }
889 #if NET_2_0
890                 [Test]
891                 public void PKCS7_ANSIX923 ()
892                 {
893                         Assert.AreEqual (4, Mismatch (PaddingMode.PKCS7, PaddingMode.ANSIX923));
894                 }
895
896                 [Test]
897                 public void PKCS7_ISO10126 ()
898                 {
899                         Assert.AreEqual (0, Mismatch (PaddingMode.PKCS7, PaddingMode.ISO10126));
900                 }
901 #endif
902                 [Test]
903                 public void PKCS7_None ()
904                 {
905                         Assert.AreEqual (1, Mismatch (PaddingMode.PKCS7, PaddingMode.None));
906                 }
907
908                 [Test]
909                 public void PKCS7_Zeros ()
910                 {
911                         Assert.AreEqual (1, Mismatch (PaddingMode.PKCS7, PaddingMode.Zeros));
912                 }
913 #if NET_2_0
914                 [Test]
915                 public void Zeros_ANSIX923 ()
916                 {
917                         Assert.AreEqual (4, Mismatch (PaddingMode.Zeros, PaddingMode.ANSIX923));
918                 }
919
920                 [Test]
921                 public void Zeros_ISO10126 ()
922                 {
923                         Assert.AreEqual (4, Mismatch (PaddingMode.Zeros, PaddingMode.ISO10126));
924                 }
925 #endif
926                 [Test]
927                 public void Zeros_None ()
928                 {
929                         Assert.AreEqual (0, Mismatch (PaddingMode.Zeros, PaddingMode.None));
930                 }
931
932                 [Test]
933                 public void Zeros_PKCS7 ()
934                 {
935 #if NET_2_0
936                         Assert.AreEqual (4, Mismatch (PaddingMode.Zeros, PaddingMode.PKCS7));
937 #else
938                         Assert.AreEqual (0, Mismatch (PaddingMode.Zeros, PaddingMode.PKCS7));
939 #endif
940                 }
941
942                 // MACTripleDES tests
943 #if NET_2_0
944                 private string MAC (PaddingMode padding, int length)
945                 {
946                         byte[] key = new byte [24] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
947                         MACTripleDES mac = new MACTripleDES (key);
948                         mac.Padding = padding;
949                         byte[] data = new byte [length];
950                         byte[] hash = mac.TransformFinalBlock (data, 0, data.Length);
951                         string result = BitConverter.ToString (mac.Hash);
952                         return result;
953                 }
954
955                 // Note: TripleDES block size is 8 bytes
956
957                 [Test]
958                 public void MACTripleDES_ANSIX923 () 
959                 {
960                         Assert.AreEqual ("F6-61-3E-C8-E4-A4-D1-A8", MAC (PaddingMode.ANSIX923, 8), "Full");
961                         Assert.AreEqual ("62-C3-78-B0-27-FC-EB-E0", MAC (PaddingMode.ANSIX923, 4), "Partial");
962                 }
963
964                 [Test]
965                 public void MACTripleDES_ISO10126 ()
966                 {
967                         // ISO 10126 use random in it's padding so we can't use it to get "repeatable" results
968                         // (i.e. each call will get different result). This isn't a padding to use for MACing!!!
969                         Assert.AreEqual (23, MAC (PaddingMode.ISO10126, 8).Length, "Full");
970                         Assert.AreEqual (23, MAC (PaddingMode.ISO10126, 4).Length, "Partial");
971                 }
972
973                 [Test]
974                 public void MACTripleDES_None ()
975                 {
976                         Assert.AreEqual ("46-34-5C-8E-EB-DC-74-5C", MAC (PaddingMode.None, 8), "Full");
977                 }
978
979                 [Test]
980                 [ExpectedException (typeof (CryptographicException))]
981                 public void MACTripleDES_None_Partial ()
982                 {
983                         // Illegal - must be a multiple of block size
984                         MAC (PaddingMode.None, 4);
985                 }
986
987                 [Test]
988                 public void MACTripleDES_PKCS7 ()
989                 {
990                         Assert.AreEqual ("17-71-9F-D5-0B-EF-1D-07", MAC (PaddingMode.PKCS7, 8), "Full");
991                         Assert.AreEqual ("5B-3A-13-6F-3F-6F-13-22", MAC (PaddingMode.PKCS7, 4), "Partial");
992                 }
993
994                 [Test]
995                 public void MACTripleDES_Zeros ()
996                 {
997                         Assert.AreEqual ("46-34-5C-8E-EB-DC-74-5C", MAC (PaddingMode.Zeros, 8));
998                         Assert.AreEqual ("46-34-5C-8E-EB-DC-74-5C", MAC (PaddingMode.Zeros, 4));
999                 }
1000
1001                 // https://bugzilla.novell.com/show_bug.cgi?id=366623
1002
1003                 [Test]
1004                 public void ANSIX923_366623 ()
1005                 {
1006                         TripleDES algo = GetTripleDES ();
1007                         algo.IV = new byte [algo.BlockSize >> 3];
1008                         algo.Mode = CipherMode.ECB;
1009                         algo.Padding = PaddingMode.ANSIX923;
1010
1011                         ICryptoTransform enc = algo.CreateEncryptor ();
1012                         byte[] data = new byte [2] { 0xff, 0xff };
1013                         byte[] encdata = enc.TransformFinalBlock (data, 0, 2);
1014                         ICryptoTransform dec = algo.CreateDecryptor ();
1015                         byte[] decdata = dec.TransformFinalBlock (encdata, 0, encdata.Length);
1016                         Assert.AreEqual (data, decdata);
1017                 }
1018 #endif
1019         }
1020 }