2009-09-22 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / corlib / Test / System.Security.Cryptography / CryptoStreamTest.cs
1 //
2 // CryptoStreamTest.cs - NUnit Test Cases for CryptoStream
3 //
4 // Author:
5 //      Sebastien Pouliot <sebastien@ximian.com>
6 //
7 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
8 // Copyright (C) 2004-2005 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 /* WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING *
31  * 
32  * DO NOT USE ANY OF THE TEST CASE AS SAMPLES FOR YOUR OWN CODE. MANY
33  * CASES CONTAINS ERRORS AND AREN'T SECURE IN THEIR USE.
34  * 
35  * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING */
36
37 using NUnit.Framework;
38 using System;
39 using System.IO;
40 using System.Reflection;
41 using System.Runtime.InteropServices;
42 using System.Security.Cryptography;
43 using System.Text;
44
45 namespace MonoTests.System.Security.Cryptography {
46
47         // much useful for debugging
48         public class DebugStream : MemoryStream {
49
50                 // constructor
51
52                 public DebugStream () : base () {}
53                 public DebugStream (byte[] buffer) : base (buffer) {}
54                 public DebugStream (int capacity) : base (capacity) {}
55
56                 public override bool CanRead {
57                         get { return base.CanRead; }
58                 }
59
60                 public override bool CanSeek {
61                         get { return base.CanSeek; }
62                 }
63
64                 public override bool CanWrite {
65                         get { return base.CanWrite; }
66                 }
67
68                 public override int Capacity {
69                         get { return base.Capacity; }
70                         set { base.Capacity = value; }
71                 }
72
73                 public override long Length {
74                         get { return base.Length; }
75                 }
76                 
77                 public override long Position {
78                         get { return base.Position; }
79                         set { base.Position = value; }
80                 }
81
82                 // methods
83                 
84                 public override void Close () 
85                 {
86                         base.Close ();
87                 }
88                 
89                 public override void Flush () 
90                 {
91                         base.Flush ();
92                 }
93
94                 public override byte[] GetBuffer () 
95                 {
96                         return base.GetBuffer ();
97                 }
98
99                 public override int Read ([In,Out] byte[] buffer, int offset, int count)
100                 {
101                         int len = base.Read (buffer, offset, count);
102                         return len;
103                 }
104
105                 public override int ReadByte () 
106                 {
107                         return base.ReadByte ();
108                 }
109
110                 public override long Seek (long offset, SeekOrigin loc)
111                 {
112                         return base.Seek (offset, loc);
113                 }
114                 
115                 public override void SetLength (long value)
116                 {
117                         base.SetLength (value);
118                 }
119                 
120                 public override byte[] ToArray () 
121                 {
122                         return base.ToArray ();
123                 }
124
125                 public override void Write (byte[] buffer, int offset, int count) 
126                 {
127                         base.Write (buffer, offset, count);
128                 }
129
130                 public override void WriteByte (byte value) 
131                 {
132                         base.WriteByte (value);
133                 }
134
135                 public override void WriteTo (Stream stream) 
136                 {
137                         base.WriteTo (stream);
138                 }
139         }
140
141         [TestFixture]
142         public class CryptoStreamTest {
143
144                 Stream readStream;
145                 Stream writeStream;
146                 ICryptoTransform encryptor;
147                 ICryptoTransform decryptor;
148                 CryptoStream cs;
149                 SymmetricAlgorithm aes;
150
151                 [SetUp]
152                 public void SetUp () 
153                 {
154                         if (readStream == null) {
155                                 readStream = new MemoryStream (new byte [0], false);
156                                 writeStream = new MemoryStream (new byte [0], true);
157                                 aes = SymmetricAlgorithm.Create ();
158                                 encryptor = aes.CreateEncryptor ();
159                                 decryptor = aes.CreateEncryptor ();
160                         }
161                 }
162
163                 public void AssertEquals (string msg, byte[] array1, byte[] array2)
164                 {
165                         Assert.AreEqual (array1, array2, msg);
166                 }
167
168                 [Test]
169                 [ExpectedException (typeof (NullReferenceException))]
170                 public void StreamNull ()
171                 {
172                         cs = new CryptoStream (null, encryptor, CryptoStreamMode.Read);
173                 }
174
175                 [Test]
176                 [ExpectedException (typeof (NullReferenceException))]
177                 public void TransformNull ()
178                 {
179                         MemoryStream write = new MemoryStream (8);
180                         byte[] data = {0, 1, 2, 3, 4, 5, 6, 7};
181                         cs = new CryptoStream (write, null, CryptoStreamMode.Write);
182                         cs.Write (data, 0, 8);
183                 }
184
185                 [Test]
186                 public void StreamReadModeRead () 
187                 {
188                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
189                         Assert.IsTrue (cs.CanRead, "Read.CanRead");
190                         Assert.IsFalse (cs.CanWrite, "Read.CanWrite");
191                         Assert.IsFalse (cs.CanSeek, "Read.CanSeek");
192                 }
193
194                 [Test]
195                 [ExpectedException (typeof (ArgumentException))]
196                 public void StreamReadModeWrite () 
197                 {
198                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Write);
199                 }
200                 
201                 [Test]
202                 [ExpectedException (typeof (ArgumentException))]
203                 public void StreamWriteModeRead () 
204                 {
205                         // This needs a stream which can't be read from; memory stream won't do that.
206                         string f = Path.GetTempFileName ();
207                         FileStream fs = new FileStream (f, FileMode.OpenOrCreate, FileAccess.Write);
208                         try {
209                                 cs = new CryptoStream (fs, encryptor, CryptoStreamMode.Read);
210                         } finally {
211                                 fs.Close ();
212                                 File.Delete (f);
213                         }
214                 }
215
216                 [Test]
217                 public void StreamWriteModeWrite () 
218                 {
219                         cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
220                         Assert.IsFalse (cs.CanRead, "Read.CanRead");
221                         Assert.IsTrue (cs.CanWrite, "Read.CanWrite");
222                         Assert.IsFalse (cs.CanSeek, "Read.CanSeek");
223                 }
224
225                 [Test]
226                 [ExpectedException (typeof (NotSupportedException))]
227                 public void GetLength () 
228                 {
229                         DebugStream debug = new DebugStream ();
230                         cs = new CryptoStream (debug, encryptor, CryptoStreamMode.Read);
231                         long x = cs.Length;
232                 }
233
234                 [Test]
235                 [ExpectedException (typeof (NotSupportedException))]
236                 public void GetPosition () 
237                 {
238                         DebugStream debug = new DebugStream ();
239                         cs = new CryptoStream (debug, encryptor, CryptoStreamMode.Read);
240                         long x = cs.Position;
241                 }
242
243                 [Test]
244                 [ExpectedException (typeof (NotSupportedException))]
245                 public void SetPosition () 
246                 {
247                         DebugStream debug = new DebugStream ();
248                         cs = new CryptoStream (debug, encryptor, CryptoStreamMode.Read);
249                         cs.Position = 1;
250                 }
251
252                 [Test]
253                 [ExpectedException (typeof (NotSupportedException))]
254                 public void Seek () 
255                 {
256                         DebugStream debug = new DebugStream ();
257                         cs = new CryptoStream (debug, encryptor, CryptoStreamMode.Read);
258                         cs.Seek (0, SeekOrigin.Begin);
259                 }
260
261                 [Test]
262                 [ExpectedException (typeof (NotSupportedException))]
263                 public void SetLength () 
264                 {
265                         DebugStream debug = new DebugStream ();
266                         cs = new CryptoStream (debug, encryptor, CryptoStreamMode.Read);
267                         cs.SetLength (0);
268                 }
269
270                 [Test]
271                 // LAMESPEC : [ExpectedException (typeof (NotSupportedException))]
272                 public void FlushReadStream () 
273                 {
274                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
275                         cs.Flush ();
276                 }
277
278                 [Test]
279 #if ONLY_1_1
280                 [ExpectedException (typeof (NotSupportedException))]
281 #endif
282                 public void FlushFinalBlockReadStream () 
283                 {
284                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
285                         cs.FlushFinalBlock ();
286                 }
287
288                 [Test]
289                 [ExpectedException (typeof (NotSupportedException))]
290                 public void FlushFinalBlock_Dual () 
291                 {
292                         // do no corrupt writeStream in further tests
293                         using (Stream s = new MemoryStream ()) {
294                                 byte[] data = {0, 1, 2, 3, 4, 5, 6, 7};
295                                 cs = new CryptoStream (s, encryptor, CryptoStreamMode.Write);
296                                 cs.Write (data, 0, data.Length);
297                                 cs.FlushFinalBlock ();
298                                 cs.FlushFinalBlock ();
299                         }
300                 }
301
302                 [Test]
303                 // LAMESPEC or MS BUG [ExpectedException (typeof (ObjectDisposedException))]
304 #if NET_2_0
305                 [ExpectedException (typeof (NotSupportedException))]
306 #else
307                 [ExpectedException (typeof (ArgumentNullException))]
308 #endif
309                 public void FlushFinalBlock_Disposed () 
310                 {
311                         // do no corrupt writeStream in further tests
312                         using (Stream s = new MemoryStream ()) {
313                                 cs = new CryptoStream (s, encryptor, CryptoStreamMode.Write);
314                                 cs.Clear ();
315                                 cs.FlushFinalBlock ();
316                         }
317                 }
318
319                 [Test]
320                 // LAMESPEC or MS BUG [ExpectedException (typeof (ObjectDisposedException))]
321 #if ONLY_1_1
322                 [ExpectedException (typeof (ArgumentNullException))]
323 #endif
324                 public void Read_Disposed () 
325                 {
326                         // do no corrupt readStream in further tests
327                         using (Stream s = new MemoryStream ()) {
328                                 byte[] buffer = new byte [8];
329                                 cs = new CryptoStream (s, encryptor, CryptoStreamMode.Read);
330                                 cs.Clear ();
331                                 Assert.AreEqual (0, cs.Read (buffer, 0, 8), "Read from disposed");
332                         }
333                 }
334
335                 [Test]
336                 // MS BUG [ExpectedException (typeof (ObjectDisposedException))]
337 #if NET_2_0
338                 [Category ("NotWorking")]
339                 [ExpectedException (typeof (IndexOutOfRangeException))]
340 #else
341                 [Category ("NotDotNet")] // Test cause System.ExecutionEngineException on MS runtime
342                 [ExpectedException (typeof (ArgumentNullException))] // should fail like previous test case
343 #endif
344                 public void Read_Disposed_Break () 
345                 {
346                         // do no corrupt readStream in further tests
347                         using (Stream s = new MemoryStream ()) {
348                                 byte[] buffer = new byte [8];
349                                 cs = new CryptoStream (s, encryptor, CryptoStreamMode.Read);
350                                 int len = cs.Read (buffer, 0, 4);
351                                 Assert.AreEqual (4, len, "Read 4");
352                                 cs.Clear ();
353                                 len = cs.Read (buffer, 3, 4);
354                         }
355                 }
356
357                 [Test]
358                 [ExpectedException (typeof (NotSupportedException))]
359                 public void Read_WriteStream () 
360                 {
361                         cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
362                         byte[] buffer = new byte [8];
363                         cs.Read (buffer, 0, 8);
364                 }
365
366                 [Test]
367                 [ExpectedException (typeof (NullReferenceException))]
368                 public void Read_NullBuffer () 
369                 {
370                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
371                         cs.Read (null, 0, 8);
372                 }
373
374                 [Test]
375                 public void Read_EmptyBuffer_ZeroCount () 
376                 {
377                         byte[] buffer = new byte [0];
378                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
379                         int len = cs.Read (buffer, 0, 0);
380                         Assert.AreEqual (0, len, "Read 0");
381                 }
382
383                 [Test]
384                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
385                 public void Read_NegativeOffset () 
386                 {
387                         byte[] buffer = new byte [8];
388                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
389                         cs.Read (buffer, -1, 8);
390                 }
391
392                 [Test]
393                 public void Read_ZeroCount () 
394                 {
395                         byte[] buffer = new byte [8];
396                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
397                         int len = cs.Read (buffer, 0, 0);
398                         Assert.AreEqual (0, len, "Read 0");
399                 }
400
401                 [Test]
402                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
403                 public void Read_NegativeCount () 
404                 {
405                         byte[] buffer = new byte [8];
406                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
407                         cs.Read (buffer, 0, -1);
408                 }
409
410                 [Test]
411                 [ExpectedException (typeof (ArgumentException))]
412                 public void Read_OverflowCount () 
413                 {
414                         byte[] buffer = new byte [8];
415                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
416                         cs.Read (buffer, 0, Int32.MaxValue);
417                 }
418
419                 [Test]
420                 [ExpectedException (typeof (ArgumentException))]
421                 public void Read_InvalidOffset () 
422                 {
423                         byte[] buffer = new byte [8];
424                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
425                         cs.Read (buffer, 5, 4);
426                 }
427
428                 [Test]
429                 [ExpectedException (typeof (ArgumentException))]
430                 public void Read_OverflowOffset () 
431                 {
432                         byte[] buffer = new byte [8];
433                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
434                         cs.Read (buffer, Int32.MaxValue, 4);
435                 }
436
437                 [Test]
438                 // MS BUG [ExpectedException (typeof (ObjectDisposedException))]
439 #if NET_2_0
440                 [Category ("NotWorking")]
441                 [ExpectedException (typeof (IndexOutOfRangeException))]
442 #else
443                 [Category ("NotDotNet")] // Test cause System.ExecutionEngineException on MS runtime
444                 [ExpectedException (typeof (ArgumentNullException))] // to match exception throw by Read in a similar case
445 #endif
446                 public void Write_Disposed () 
447                 {
448                         // do no corrupt writeStream in further tests
449                         using (Stream s = new MemoryStream ()) {
450                                 byte[] buffer = new byte [8];
451                                 cs = new CryptoStream (s, encryptor, CryptoStreamMode.Write);
452                                 cs.Clear ();
453                                 cs.Write (buffer, 0, 8);
454                         }
455                 }
456
457                 [Test]
458                 [ExpectedException (typeof (NotSupportedException))]
459                 public void Write_ReadStream () 
460                 {
461                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
462                         byte[] buffer = new byte [8];
463                         cs.Write (buffer, 0, 8);
464                 }
465
466                 [Test]
467                 [ExpectedException (typeof (NullReferenceException))]
468                 public void Write_NullBuffer () 
469                 {
470                         cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
471                         cs.Write (null, 0, 8);
472                 }
473
474                 [Test]
475                 public void Write_EmptyBuffer_ZeroCount () 
476                 {
477                         byte[] buffer = new byte [0];
478                         cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
479                         cs.Write (buffer, 0, 0);
480                 }
481
482                 [Test]
483                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
484                 public void Write_NegativeOffset () 
485                 {
486                         byte[] buffer = new byte [8];
487                         cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
488                         cs.Write (buffer, -1, 8);
489                 }
490
491                 [Test]
492                 [ExpectedException (typeof (ArgumentException))]
493                 public void Write_OverflowOffset () 
494                 {
495                         byte[] buffer = new byte [8];
496                         cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
497                         cs.Write (buffer, Int32.MaxValue, 8);
498                 }
499
500                 [Test]
501                 public void Write_ZeroCount () 
502                 {
503                         byte[] buffer = new byte [8];
504                         cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
505                         cs.Write (buffer, 0, 0);
506                 }
507
508                 [Test]
509                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
510                 public void Write_NegativeCount () 
511                 {
512                         byte[] buffer = new byte [8];
513                         cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
514                         cs.Write (buffer, 0, -1);
515                 }
516
517                 [Test]
518                 [ExpectedException (typeof (ArgumentException))]
519                 public void Write_InvalidOffset () 
520                 {
521                         DebugStream debug = new DebugStream ();
522                         byte[] buffer = new byte [8];
523                         cs = new CryptoStream (debug, encryptor, CryptoStreamMode.Write);
524                         cs.Write (buffer, 5, 4);
525                 }
526
527                 [Test]
528                 [ExpectedException (typeof (ArgumentException))]
529                 public void Write_OverflowCount () 
530                 {
531                         DebugStream debug = new DebugStream ();
532                         byte[] buffer = new byte [8];
533                         cs = new CryptoStream (debug, encryptor, CryptoStreamMode.Write);
534                         cs.Write (buffer, 0, Int32.MaxValue);
535                 }
536
537                 [Test]
538                 public void FullRoundtripRead () 
539                 {
540                         byte[] encrypted;
541                         using (DebugStream mem1 = new DebugStream ()) {
542                                 byte[] toEncrypt = Encoding.Unicode.GetBytes ("Please encode me!");
543                                 using (CryptoStream crypt = new CryptoStream (mem1, aes.CreateEncryptor (), CryptoStreamMode.Write)) {
544                                         crypt.Write (toEncrypt, 0, toEncrypt.Length);
545                                         crypt.FlushFinalBlock ();
546                                 }
547                                 encrypted = mem1.ToArray ();
548                         }
549                                         
550                         using (DebugStream mem2 = new DebugStream (encrypted)) {
551                                 byte[] buffer = new byte [1024];
552                                 CryptoStream cr = new CryptoStream (mem2, aes.CreateDecryptor (), CryptoStreamMode.Read);
553                                 int len = cr.Read (buffer, 0, buffer.Length);
554                                 cr.Close ();
555                                 Assert.AreEqual (34, len, "Full Length Read");
556                                 Assert.AreEqual ("Please encode me!", Encoding.Unicode.GetString (buffer, 0, len), "Full Block Read");
557                         }
558                 }
559
560                 // bugzilla 46143 (adapted from test case by Joerg Rosenkranz)
561                 [Test]
562                 public void PartialRoundtripRead () 
563                 {
564                         byte[] encrypted;
565                         using (DebugStream mem1 = new DebugStream ()) {
566                                 byte[] toEncrypt = Encoding.Unicode.GetBytes ("Please encode me!");
567                                 using (CryptoStream crypt = new CryptoStream (mem1, aes.CreateEncryptor (), CryptoStreamMode.Write)) {
568                                         crypt.Write (toEncrypt, 0, toEncrypt.Length);
569                                         crypt.FlushFinalBlock ();
570                                 }
571                                 encrypted = mem1.ToArray ();
572                         }
573                                         
574                         using (DebugStream mem2 = new DebugStream (encrypted)) {
575                                 byte[] buffer = new byte [1024];
576                                 CryptoStream cr = new CryptoStream (mem2, aes.CreateDecryptor (), CryptoStreamMode.Read);
577                                 int len = cr.Read (buffer, 0, 20);
578                                 cr.Clear ();
579                                 cr.Close ();
580                                 Assert.AreEqual (20, len, "Partial Length Read");
581                                 Assert.AreEqual ("Please enc", Encoding.Unicode.GetString (buffer, 0, len), "Partial Block Read");
582                         }
583                 }
584
585                 // bugzilla: 40689 (adapted from test case by Henning Westerholt)
586                 [Test]
587                 public void WriteOnBlockWithFinal () 
588                 {
589                         byte[] desKey = {0, 1, 2, 3, 4, 5, 6, 7};
590                         byte[] desIV = {0, 1, 2, 3, 4, 5, 6, 7};
591                         DES des = DES.Create ();
592
593                         MemoryStream msin = new MemoryStream ();
594                         CryptoStream enc = new CryptoStream (msin, des.CreateEncryptor (desKey, desIV), CryptoStreamMode.Write);
595                         byte[] data = new byte [2200];
596                         enc.Write (data, 0, 2200);
597                         enc.FlushFinalBlock ();
598                         msin.Position = 0;
599                         Assert.AreEqual (2208, msin.Length, "Encryped Write Length"); // 2200 + padding
600
601                         MemoryStream msout = new MemoryStream ();
602                         msout.SetLength (0);
603
604                         byte[] tmp = new byte [1024];
605                         long readlen = 0;
606                         long totallen = msin.Length;
607
608                         CryptoStream dec = new CryptoStream (msout, des.CreateDecryptor (desKey, desIV), CryptoStreamMode.Write);
609                         int len = msin.Read (tmp, 0, 1024);
610                         while (len > 0) {
611                                 dec.Write (tmp, 0, len);
612                                 readlen += len;
613                                 len = msin.Read (tmp, 0, 1024);
614                         }
615                         Assert.AreEqual (2200, msout.Length, "Decryped Write Length");
616
617                         dec.Close ();
618                         dec.Clear ();
619                         msout.Close ();
620                         msin.Close ();
621
622                         Assert.AreEqual (2208, readlen, "Read Length"); // 2200 + padding
623                 }
624
625                 [Test]
626                 public void PreGeneratedStreams ()
627                 {
628                         byte[] desKey = {0, 1, 2, 3, 4, 5, 6, 7};
629                         byte[] desIV = {0, 1, 2, 3, 4, 5, 6, 7};
630                         DES des = DES.Create ();
631         
632                         for (int i=0; i < 9; i++) {
633                                 MemoryStream msin = new MemoryStream ();
634                                 CryptoStream enc = new CryptoStream (msin, des.CreateEncryptor (desKey, desIV), CryptoStreamMode.Write);
635                                 byte[] data = new byte [i];
636                                 enc.Write (data, 0, i);
637                                 enc.FlushFinalBlock ();
638
639                                 string msg = "PreGeneratedStream #" + i;
640                                 string result = BitConverter.ToString (msin.ToArray ());
641                                 switch (i) {
642                                         case 0:
643                                                 Assert.AreEqual ("92-C9-DB-45-30-0B-93-2F", result, msg); 
644                                                 break;
645                                         case 1:
646                                                 Assert.AreEqual ("08-CF-A1-37-BD-56-D0-65", result, msg); 
647                                                 break;
648                                         case 2:
649                                                 Assert.AreEqual ("58-87-D4-9B-2C-27-97-0C", result, msg); 
650                                                 break;
651                                         case 3:
652                                                 Assert.AreEqual ("07-35-90-94-68-7D-51-FB", result, msg); 
653                                                 break;
654                                         case 4:
655                                                 Assert.AreEqual ("BF-00-98-C5-20-71-D0-DB", result, msg); 
656                                                 break;
657                                         case 5:
658                                                 Assert.AreEqual ("1A-55-C8-6E-C1-9B-31-82", result, msg); 
659                                                 break;
660                                         case 6:
661                                                 Assert.AreEqual ("2D-2B-76-41-61-0E-00-0C", result, msg); 
662                                                 break;
663                                         case 7:
664                                                 Assert.AreEqual ("DC-FF-73-D2-7F-D7-48-5D", result, msg); 
665                                                 break;
666                                         case 8:
667                                                 Assert.AreEqual ("E1-B2-46-E5-A7-C7-4C-BC-0E-40-4A-FC-08-92-B1-EB", result, msg); 
668                                                 break;
669                                 }
670                         }
671                 }
672
673                 private byte[] EmptyStream (PaddingMode mode) 
674                 {
675                         SymmetricAlgorithm algo = Rijndael.Create ();
676                         algo.Key = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
677                         algo.IV = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
678                         algo.Padding = mode;
679                         MemoryStream ms = new MemoryStream ();
680                         CryptoStream cs = new CryptoStream (ms, algo.CreateEncryptor(), CryptoStreamMode.Write);
681                         cs.Write (ms.GetBuffer (), 0, (int) ms.Length);
682                         cs.FlushFinalBlock ();
683                         cs.Flush ();
684                         return ms.ToArray ();
685                 }
686
687                 [Test]
688                 public void EmptyStreamWithPaddingNone () 
689                 {
690                         byte[] result = EmptyStream (PaddingMode.None);
691                         Assert.AreEqual (0, result.Length, "Result Length");
692                 }
693
694                 [Test]
695                 public void EmptyStreamWithPaddingPKCS7 () 
696                 {
697                         byte[] expected = { 0x07, 0xFE, 0xEF, 0x74, 0xE1, 0xD5, 0x03, 0x6E, 0x90, 0x0E, 0xEE, 0x11, 0x8E, 0x94, 0x92, 0x93 };
698                         byte[] result = EmptyStream (PaddingMode.PKCS7);
699                         Assert.AreEqual (16, result.Length, "Result Length");
700                         Assert.AreEqual (expected, result, "Result");
701                 }
702
703                 [Test]
704                 public void EmptyStreamWithPaddingZeros () 
705                 {
706                         byte[] result = EmptyStream (PaddingMode.Zeros);
707                         Assert.AreEqual (0, result.Length, "Result Length");
708                 }
709
710                 // bugzilla: 49323 (adapted from test case by Carlos Guzmán Álvarez)
711                 [Test]
712                 public void MultiblocksWithPartial () 
713                 {
714                         SymmetricAlgorithm tdes = new TripleDESCryptoServiceProvider ();
715                         tdes.Key = new byte[] {161, 54, 179, 213, 89, 75, 130, 4, 186, 99, 158, 127, 19, 195, 175, 143, 79, 109, 25, 202, 237, 235, 62, 170};
716                         tdes.IV = new byte[] {193, 227, 54, 132, 68, 172, 55, 91};
717
718                         byte[] fragment = new byte[] {20, 0, 0, 12, 181, 134, 8, 230, 185, 75, 19, 129, 101, 142, 118, 190};
719                         byte[] mac = new byte[] {42, 148, 229, 58, 185, 249, 154, 131, 157, 79, 176, 168, 143, 71, 0, 118, 5, 10, 95, 8};
720                                                                                                                                                                                                   
721                         // Encryption ( fragment + mac [+ padding + padding_length] )
722                         MemoryStream ms = new MemoryStream ();
723                         CryptoStream cs = new CryptoStream (ms, tdes.CreateEncryptor (), CryptoStreamMode.Write);
724                         cs.Write (fragment, 0, fragment.Length);
725                         cs.Write (mac, 0, mac.Length);
726                         // Calculate padding_length
727                         int fragmentLength = fragment.Length + mac.Length + 1;
728                         int padding = (((fragmentLength / 8) * 8) + 8) - fragmentLength;
729                         // Write padding length byte
730                         cs.WriteByte ((byte)padding);
731                         cs.Close ();
732                         byte[] encrypted = ms.ToArray ();
733                         byte[] expected = new byte[] { 0x9c, 0x99, 0x56, 0x8e, 0x75, 0x3e, 0x02, 0x95, 0x5b, 0x5c, 0x46, 0x8b, 0xcf, 0xf8, 0x27, 0x21, 0x53, 0x5f, 0x3d, 0xd8, 0x16, 0x95, 0x82, 0x3d, 0x88, 0x9b, 0x9a, 0x47, 0xda, 0x97, 0x90, 0x86, 0x50, 0x0e, 0x48, 0xee, 0xe7, 0x9b, 0x25, 0x41 };
734                         Assert.AreEqual (expected, encrypted, "MultiblocksWithPartial");
735                 }
736
737                 // Adapted from Subba Rao Thirumoorthy email on mono-devel-list (december 2003)
738                 private byte[] NonMultipleOfBlockSize_Encrypt (ICryptoTransform ct, byte[] data)
739                 {
740                         DebugStream stream = new DebugStream ();
741                         CryptoStream CryptStream = new CryptoStream (stream, ct, CryptoStreamMode.Write);
742
743                         int len = 0;
744                         long myLength = 0;
745                         byte[] Buffer = new byte [1024];
746                         
747                         DebugStream fout = new DebugStream (data);
748                         while (myLength < data.Length) {
749                                 len = fout.Read (Buffer, 0, 1023);
750                                 if (len == 0)
751                                         break;
752                                 CryptStream.Write (Buffer, 0, len);
753                                 CryptStream.Flush ();
754                                 myLength = myLength + len;
755                         }
756                         CryptStream.FlushFinalBlock ();
757                         // we must ensure that the result is correct
758                         Assert.AreEqual (64, len, "Length(final)");
759                         byte[] result = stream.ToArray ();
760                         string end = BitConverter.ToString (result, 65520, 16);
761                         Assert.AreEqual ("04-70-19-1D-28-C5-BD-9A-23-C6-60-E2-28-96-38-65", end, "End part");
762
763                         CryptStream.Close();
764                         stream.Close();
765                         return result;
766                 }
767
768                 private byte[] NonMultipleOfBlockSize_Decrypt (ICryptoTransform ct, byte[] data) 
769                 {
770                         DebugStream stream = new DebugStream (data);
771                         CryptoStream CryptStream = new CryptoStream (stream, ct, CryptoStreamMode.Read);
772
773                         int len = 0;
774                         long myLength = 0;
775                         byte[] Buffer = new Byte [1024];
776
777                         DebugStream fout = new DebugStream ();
778                         // each returned block must be 1023 bytes long 
779                         // even if this isn't a multiple of the block size
780                         while ((len = CryptStream.Read (Buffer, 0, 1023)) != 0) {
781                                 fout.Write (Buffer, 0, len);
782                                 fout.Flush ();
783                                 myLength = myLength + len;
784                         }
785
786                         byte[] result = fout.ToArray ();
787                         CryptStream.Close ();
788                         stream.Close ();
789                         return result;
790                 }
791
792                 [Test]
793                 public void NonMultipleOfBlockSize ()
794                 {
795                         byte[] key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
796                         byte[] iv  = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
797                         byte[] data = new byte [65536];
798
799                         RijndaelManaged aes = new RijndaelManaged ();
800                         ICryptoTransform encryptor = aes.CreateEncryptor (key, iv);
801                         byte[] encdata = NonMultipleOfBlockSize_Encrypt (encryptor, data);
802                         Assert.AreEqual ((data.Length + (aes.BlockSize >> 3)), encdata.Length, "Encrypted Data Length");
803                         
804                         ICryptoTransform decryptor = aes.CreateDecryptor (key, iv);
805                         byte[] decdata = NonMultipleOfBlockSize_Decrypt (decryptor, encdata);
806                         Assert.AreEqual (data.Length, decdata.Length, "Decrypted Data Length");
807
808                         int i = 0;
809                         bool b = true;
810                         while (b && (i < data.Length)) {
811                                 b = (data [i] == decdata [i]);
812                                 i++;
813                         }
814                         Assert.IsTrue (b, "NonMultipleOfBlockSize");
815                 }
816
817                 // bugzilla: 51322 - indirectly related but it explains why my first (unapplied) patch didn't work
818                 [Test]
819                 public void DecryptPartial_TransformFinalBlock_required () 
820                 {
821                         byte[] key = {0, 1, 2, 3, 4, 5, 6, 7};
822                         byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7};
823                         DES des = DES.Create ();
824
825                         byte[] data = Encoding.Unicode.GetBytes ("ximian");     // 12 bytes, 1.5 DES block size
826                         DebugStream encrypted = new DebugStream ();
827                         cs = new CryptoStream (encrypted, des.CreateEncryptor (key, iv), CryptoStreamMode.Write);
828                         cs.Write (data, 0, data.Length);
829                         cs.Close ();
830
831                         data = encrypted.ToArray ();
832                         DebugStream decrypted = new DebugStream (data);
833                         cs = new CryptoStream (decrypted, des.CreateDecryptor (key, iv), CryptoStreamMode.Read);
834                         int len = cs.Read (data, 0, data.Length);
835                         cs.Close ();
836                         Assert.AreEqual (12, len, "Length");
837                         Assert.AreEqual ("ximian", Encoding.Unicode.GetString (data, 0, len), "Unicode DES Roundtrip");
838                 }
839
840 #if NET_2_0
841                 [Category ("NotWorking")]
842 #endif          
843                 [Test]
844                 public void DecryptPartial_TransformFinalBlock_2Pass () 
845                 {
846                         byte[] key = {0, 1, 2, 3, 4, 5, 6, 7};
847                         byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7};
848                         DES des = DES.Create ();
849
850                         byte[] data = Encoding.Unicode.GetBytes ("ximian");     // 12 bytes, 1.5 DES block size
851                         DebugStream encrypted = new DebugStream ();
852                         cs = new CryptoStream (encrypted, des.CreateEncryptor (key, iv), CryptoStreamMode.Write);
853                         cs.Write (data, 0, data.Length);
854                         cs.Close ();
855
856                         data = encrypted.ToArray ();
857                         DebugStream decrypted = new DebugStream (data);
858                         cs = new CryptoStream (decrypted, des.CreateDecryptor (key, iv), CryptoStreamMode.Read);
859                         int len = cs.Read (data, 0, 6);
860                         Assert.AreEqual (6, len, "Length (1st pass)");
861                         Assert.AreEqual ("xim", Encoding.Unicode.GetString (data, 0, len), "Partial DES Roundtrip");
862                         len += cs.Read (data, 6, 8);
863                         Assert.AreEqual (12, len, "Length (1st+2nd)");
864                         Assert.AreEqual ("ximian", Encoding.Unicode.GetString (data, 0, len), "Full DES Roundtrip");
865                         cs.Close ();
866                 }
867
868                 // based on http://www.c-sharpcorner.com/Code/2002/May/FileEncryption.asp
869 #if NET_2_0
870                 [Category ("NotWorking")]
871 #endif  
872                 [Test]
873                 public void WriteByteReadByte () 
874                 {
875                         DebugStream original = new DebugStream (Encoding.Unicode.GetBytes ("ximian"));
876
877                         DebugStream encrypted = new DebugStream ();
878                         byte[] key = {0, 1, 2, 3, 4, 5, 6, 7};
879                         byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7};
880                         DES des = DES.Create ();
881                         cs = new CryptoStream (encrypted, des.CreateEncryptor (key, iv), CryptoStreamMode.Write);
882
883                         int data;
884                         while ((data = original.ReadByte ()) != -1)
885                                 cs.WriteByte((byte) data);
886                         cs.Close ();
887
888                         byte[] result = encrypted.ToArray ();
889                         Assert.AreEqual ("18-EA-93-3F-20-86-D2-AA-78-02-D7-6F-E4-47-17-9C", BitConverter.ToString (result), "Encrypted");
890
891                         encrypted = new DebugStream (result);
892                         DebugStream decrypted = new DebugStream ();
893                         cs = new CryptoStream (encrypted, des.CreateDecryptor (key, iv), CryptoStreamMode.Read);
894
895                         while ((data = cs.ReadByte ()) != -1)
896                                 decrypted.WriteByte((byte) data);
897                         cs.Close ();
898                         decrypted.Close ();
899
900                         Assert.AreEqual ("ximian", Encoding.Unicode.GetString (decrypted.ToArray ()), "W/R Byte Roundtrip");
901                 }
902
903                 // based http://www.4guysfromrolla.com/webtech/090501-1.shtml
904
905                 public string EncryptData (ICryptoTransform des, string strData) 
906                 {
907                         strData = String.Format("{0,5:00000}" + strData, strData.Length);
908                         byte[] data = Encoding.ASCII.GetBytes (strData);
909
910                         MemoryStream mStream = new MemoryStream (data); 
911                         CryptoStream cs = new CryptoStream (mStream, des, CryptoStreamMode.Read);        
912                         MemoryStream mOut = new MemoryStream ();
913         
914                         int bytesRead; 
915                         byte[] output = new byte [1024]; 
916                         do { 
917                                 bytesRead = cs.Read (output, 0, 1024);
918                                 if (bytesRead != 0) 
919                                         mOut.Write (output, 0, bytesRead); 
920                         } 
921                         while (bytesRead > 0); 
922         
923                         return Convert.ToBase64String (mOut.ToArray ());
924                 }
925
926                 public string DecryptData (ICryptoTransform des, string strData) 
927                 {
928                         MemoryStream mOut = new MemoryStream ();
929                         byte[] data = Convert.FromBase64String (strData);
930                         CryptoStream cs = new CryptoStream (mOut, des, CryptoStreamMode.Write);        
931                         cs.Write (data, 0, (int)data.Length);
932                         cs.FlushFinalBlock ();
933                         return Encoding.ASCII.GetString (mOut.ToArray ()).Substring (5);
934                 }
935
936                 [Test]
937                 public void EncryptOnRead () 
938                 {
939                         SHA1 sha = SHA1.Create ();
940                         byte[] vector = sha.ComputeHash (Encoding.ASCII.GetBytes ("s3kr3t"));
941                         byte[] key = new byte [8];
942                         Buffer.BlockCopy (vector, 0, key, 0, key.Length);
943                         byte[] iv = new byte [8];
944                         Buffer.BlockCopy (vector, 8, iv, 0, iv.Length);
945
946                         DES des = DES.Create ();
947
948                         StringBuilder sb = new StringBuilder ();
949                         sb.Append ("a");
950                         string data = sb.ToString ();
951                         string encdata = EncryptData (des.CreateEncryptor (key, iv), data);
952                         string decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
953                         Assert.AreEqual ("9YVfvrh5yj0=", encdata, "Encrypt-" + data);
954                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
955
956                         sb.Append ("a");
957                         data = sb.ToString ();
958                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
959                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
960                         Assert.AreEqual ("qNe4d0UlkU8=", encdata, "Encrypt-" + data);
961                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
962
963                         sb.Append ("a");
964                         data = sb.ToString ();
965                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
966                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
967                         Assert.AreEqual ("OcernYAQ1NAME/Gny+ZuaA==", encdata, "Encrypt-" + data);
968                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
969
970                         sb.Append ("a");
971                         data = sb.ToString ();
972                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
973                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
974                         Assert.AreEqual ("H5UveR2lds1T+IWN4pks2Q==", encdata, "Encrypt-" + data);
975                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
976
977                         sb.Append ("a");
978                         data = sb.ToString ();
979                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
980                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
981                         Assert.AreEqual ("dDQ3HAVtTbiRwwUqWANaeA==", encdata, "Encrypt-" + data);
982                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
983
984                         sb.Append ("a");
985                         data = sb.ToString ();
986                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
987                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
988                         Assert.AreEqual ("At1r7dVDjJlQidf4QzCNkw==", encdata, "Encrypt-" + data);
989                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
990
991                         sb.Append ("a");
992                         data = sb.ToString ();
993                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
994                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
995                         Assert.AreEqual ("DFDJWJGaNrFVBDXovsq1ew==", encdata, "Encrypt-" + data);
996                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
997
998                         sb.Append ("a");
999                         data = sb.ToString ();
1000                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1001                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1002                         Assert.AreEqual ("gM040QGMPOBj3u1lEK4XHQ==", encdata, "Encrypt-" + data);
1003                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1004
1005                         sb.Append ("a");
1006                         data = sb.ToString ();
1007                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1008                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1009                         Assert.AreEqual ("P5hRUhrxOWFX0ER/IjJL/Q==", encdata, "Encrypt-" + data);
1010                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1011
1012                         sb.Append ("a");
1013                         data = sb.ToString ();
1014                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1015                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1016                         Assert.AreEqual ("uDIaQ1uXtWUIboGFLt306Q==", encdata, "Encrypt-" + data);
1017                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1018
1019                         sb.Append ("a");
1020                         data = sb.ToString ();
1021                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1022                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1023                         Assert.AreEqual ("giJKTXfad5Z8hebhXtYZ4hmKX/EC8w6x", encdata, "Encrypt-" + data);
1024                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1025
1026                         sb.Append ("a");
1027                         data = sb.ToString ();
1028                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1029                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1030                         Assert.AreEqual ("lBehBplIrjjrlIrMjYcNz1DOoXLHjZdn", encdata, "Encrypt-" + data);
1031                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1032
1033                         sb.Append ("a");
1034                         data = sb.ToString ();
1035                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1036                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1037                         Assert.AreEqual ("2elWrUnjmsAOpo2s4voJyZXEJ/rtKB7P", encdata, "Encrypt-" + data);
1038                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1039
1040                         sb.Append ("a");
1041                         data = sb.ToString ();
1042                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1043                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1044                         Assert.AreEqual ("GB3BaIZGf9K+T82j7T8Fri2rQ2/YUdSe", encdata, "Encrypt-" + data);
1045                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1046
1047                         sb.Append ("a");
1048                         data = sb.ToString ();
1049                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1050                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1051                         Assert.AreEqual ("Gc+wkJL+CVjdJchgcIoi8dkH2BVpHJgB", encdata, "Encrypt-" + data);
1052                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1053
1054                         sb.Append ("a");
1055                         data = sb.ToString ();
1056                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1057                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1058                         Assert.AreEqual ("loeuyII/PvWb91M4pFVkyaPxQoQVYpNb", encdata, "Encrypt-" + data);
1059                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1060
1061                         sb.Append ("a");
1062                         data = sb.ToString ();
1063                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1064                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1065                         Assert.AreEqual ("PHXmi/sxNIgApXAfdm+Bf54/nCM//N8o", encdata, "Encrypt-" + data);
1066                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1067
1068                         sb.Append ("a");
1069                         data = sb.ToString ();
1070                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1071                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1072                         Assert.AreEqual ("xpb+wj/8LmH2ScTg3OU4JOsE5Owj6flF", encdata, "Encrypt-" + data);
1073                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1074
1075                         sb.Append ("a");
1076                         data = sb.ToString ();
1077                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1078                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1079                         Assert.AreEqual ("WJz4VfsZ2emzhYWoSf+PNBDpHooxEregqMWnzm4gcqU=", encdata, "Encrypt-" + data);
1080                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1081
1082                         sb.Append ("a");
1083                         data = sb.ToString ();
1084                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1085                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1086                         Assert.AreEqual ("PaouZu1iOKbCMRJSu04y/kB+TcOk4yp8K2BOGDs1PPE=", encdata, "Encrypt-" + data);
1087                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1088
1089                         sb.Append ("a");
1090                         data = sb.ToString ();
1091                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1092                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1093                         Assert.AreEqual ("qbTDs4dFy7eERdn5vV7JRPk2/m9smtwvZjA6+TmGlkI=", encdata, "Encrypt-" + data);
1094                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1095
1096                         sb.Append ("a");
1097                         data = sb.ToString ();
1098                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1099                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1100                         Assert.AreEqual ("f2FsphcpM7Fu90S5V17ptly44lL4GvFCCaFdnnU4twk=", encdata, "Encrypt-" + data);
1101                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1102
1103                         sb.Append ("a");
1104                         data = sb.ToString ();
1105                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1106                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1107                         Assert.AreEqual ("imD+ntHsUmp9ALJedzC1JmAJY0r2O4KkP8271+XuG4g=", encdata, "Encrypt-" + data);
1108                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1109
1110                         sb.Append ("a");
1111                         data = sb.ToString ();
1112                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1113                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1114                         Assert.AreEqual ("80QLLUmHwx1fcEYGeFz1WXlS13kUy994sQLI6GhcjuM=", encdata, "Encrypt-" + data);
1115                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1116
1117                         sb.Append ("a");
1118                         data = sb.ToString ();
1119                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1120                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1121                         Assert.AreEqual ("DtIIlj8BCOppmIgQ9AEdUj7pBB49S/9Q38kbWLjwiVs=", encdata, "Encrypt-" + data);
1122                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1123
1124                         sb.Append ("a");
1125                         data = sb.ToString ();
1126                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1127                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1128                         Assert.AreEqual ("LNkprYaaUFtyan204OzX+a2pzOb/Pg5WXzXJ6WWB1rQ=", encdata, "Encrypt-" + data);
1129                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1130
1131                         sb.Append ("a");
1132                         data = sb.ToString ();
1133                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1134                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1135                         Assert.AreEqual ("FRgx9m2lT2PxtYSIdRwc+SznJetNiRk1MEIZDl3D13pvo2yOtJ1MSQ==", encdata, "Encrypt-" + data);
1136                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1137
1138                         sb.Append ("a");
1139                         data = sb.ToString ();
1140                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1141                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1142                         Assert.AreEqual ("V7JlnpJscrdIpX4z5S+/Q5WDjKzK4aB5TiqI3JZOYJ+KE1CWQNNeow==", encdata, "Encrypt-" + data);
1143                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1144
1145                         sb.Append ("a");
1146                         data = sb.ToString ();
1147                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1148                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1149                         Assert.AreEqual ("wVwPv1c2KQynbwiOBCAhmQlReOQT52qFR34AX4dtjEeQ1oCQ1N1tHg==", encdata, "Encrypt-" + data);
1150                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1151
1152                         sb.Append ("a");
1153                         data = sb.ToString ();
1154                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1155                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1156                         Assert.AreEqual ("Zi+G0yfmuFjSjP455pjVeKBDDWB4qvTb0K0h20UtflrYG6wcWqUzDw==", encdata, "Encrypt-" + data);
1157                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1158
1159                         sb.Append ("a");
1160                         data = sb.ToString ();
1161                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1162                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1163                         Assert.AreEqual ("0hGoonZ8jrLhMNDKBuWrlvFnq15ZLvnyq+Ilq8r4aYUEDxttQMwi5w==", encdata, "Encrypt-" + data);
1164                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1165                 }
1166
1167                 // based on System.Security assembly XmlDsigBase64TransformTest
1168
1169                 [Test]
1170                 public void FromBase64_Write () 
1171                 {
1172                         string expected = "http://www.go-mono.com/";
1173                         byte[] data = Encoding.UTF8.GetBytes (expected);
1174                         string temp = Convert.ToBase64String (data, 0, data.Length);
1175                         data = Encoding.UTF8.GetBytes (temp);
1176
1177                         DebugStream debug = new DebugStream ();
1178                         ICryptoTransform base64 = new FromBase64Transform ();
1179                         cs = new CryptoStream (debug, base64, CryptoStreamMode.Write);
1180                         cs.Write (data, 0, data.Length);
1181                         cs.FlushFinalBlock ();
1182                         byte[] encoded = debug.ToArray ();
1183
1184                         string result = Encoding.UTF8.GetString (encoded);
1185                         Assert.AreEqual (expected, result, "FromBase64_Write");
1186                 }
1187
1188                 [Test]
1189                 public void FromBase64_Read () 
1190                 {
1191                         byte[] original = Encoding.UTF8.GetBytes ("aHR0cDovL3d3dy5nby1tb25vLmNvbS8=");
1192                         DebugStream debug = new DebugStream (original);
1193
1194                         ICryptoTransform base64 = new FromBase64Transform ();
1195                         cs = new CryptoStream (debug, base64, CryptoStreamMode.Read);
1196                         
1197                         byte[] data = new byte [1024];
1198                         int length = cs.Read (data, 0, data.Length);
1199                         cs.Close ();
1200
1201                         string result = Encoding.UTF8.GetString (data, 0, length);
1202                         Assert.AreEqual ("http://www.go-mono.com/", result, "ToBase64_Read");
1203                 }
1204
1205                 [Test]
1206                 public void ToBase64_Write () 
1207                 {
1208                         byte[] data = Encoding.UTF8.GetBytes ("http://www.go-mono.com/");
1209
1210                         DebugStream debug = new DebugStream ();
1211                         ICryptoTransform base64 = new ToBase64Transform ();
1212                         cs = new CryptoStream (debug, base64, CryptoStreamMode.Write);
1213                         cs.Write (data, 0, data.Length);
1214                         cs.FlushFinalBlock ();
1215                         byte[] encoded = debug.ToArray ();
1216
1217                         string result = Encoding.UTF8.GetString (encoded);
1218                         Assert.AreEqual ("aHR0cDovL3d3dy5nby1tb25vLmNvbS8=", result, "ToBase64_Write");
1219                 }
1220
1221                 [Test]
1222                 public void ToBase64_Read () 
1223                 {
1224                         byte[] original = Encoding.UTF8.GetBytes ("http://www.go-mono.com/");
1225                         DebugStream debug = new DebugStream (original);
1226
1227                         ICryptoTransform base64 = new ToBase64Transform ();
1228                         cs = new CryptoStream (debug, base64, CryptoStreamMode.Read);
1229                         
1230                         byte[] data = new byte [1024];
1231                         int length = cs.Read (data, 0, data.Length);
1232                         cs.Close ();
1233
1234                         string result = Encoding.UTF8.GetString (data, 0, length);
1235                         Assert.AreEqual ("aHR0cDovL3d3dy5nby1tb25vLmNvbS8=", result, "ToBase64_Read");
1236                 }
1237
1238                 // Cascaded CryptoStream - like sample in book .NET Framework Security, chapter 30
1239
1240                 [Test]
1241                 public void CascadedCryptoStream_Write () 
1242                 {
1243                         DebugStream debug = new DebugStream ();
1244
1245                         // calculate both the hash (before encryption) and encrypt in one Write operation
1246                         byte[] key = {0, 1, 2, 3, 4, 5, 6, 7};
1247                         byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7};
1248                         DES des = DES.Create ();
1249                         CryptoStream cse = new CryptoStream (debug, des.CreateEncryptor (key, iv), CryptoStreamMode.Write);
1250
1251                         MD5 hash = MD5.Create ();
1252                         CryptoStream csh = new CryptoStream (cse, hash, CryptoStreamMode.Write);
1253
1254                         byte[] data = Encoding.UTF8.GetBytes ("http://www.go-mono.com/");
1255                         csh.Write (data, 0, data.Length);
1256                         csh.FlushFinalBlock ();
1257
1258                         byte[] result = debug.ToArray ();
1259                         Assert.AreEqual ("8C-24-76-74-09-79-2B-D3-47-C3-32-F5-F3-1A-5E-57-04-33-2E-B8-50-77-B2-A1", BitConverter.ToString (result), "Encrypted");
1260                         byte[] digest = hash.Hash;
1261                         Assert.AreEqual ("71-04-12-D1-95-01-CF-F9-8D-8F-F8-0D-F9-AA-11-7D", BitConverter.ToString (digest), "Hash");
1262                 }
1263 #if NET_2_0
1264                 [Category ("NotWorking")]
1265 #endif  
1266                 [Test]
1267                 public void CascadedCryptoStream_Read () 
1268                 {
1269                         byte[] encdata = new byte[] { 0x8C, 0x24, 0x76, 0x74, 0x09, 0x79, 0x2B, 0xD3, 0x47, 0xC3, 0x32, 0xF5, 0xF3, 0x1A, 0x5E, 0x57, 0x04, 0x33, 0x2E, 0xB8, 0x50, 0x77, 0xB2, 0xA1 };
1270                         DebugStream debug = new DebugStream (encdata);
1271
1272                         // decrypt data and validate its hash in one Read operation
1273                         byte[] key = {0, 1, 2, 3, 4, 5, 6, 7};
1274                         byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7};
1275                         DES des = DES.Create ();
1276                         CryptoStream csd = new CryptoStream (debug, des.CreateDecryptor (key, iv), CryptoStreamMode.Read);
1277
1278                         MD5 hash = MD5.Create ();
1279                         CryptoStream csh = new CryptoStream (csd, hash, CryptoStreamMode.Read);
1280
1281                         byte[] data = new byte [1024];
1282                         int length = csh.Read (data, 0, data.Length);
1283                         csh.Close ();
1284                         
1285                         string result = Encoding.UTF8.GetString (data, 0, length);
1286                         Assert.AreEqual ("http://www.go-mono.com/", result, "Decrypted");
1287                         byte[] digest = hash.Hash;
1288                         Assert.AreEqual ("71-04-12-D1-95-01-CF-F9-8D-8F-F8-0D-F9-AA-11-7D", BitConverter.ToString (digest), "Hash Validation");
1289                 }
1290
1291                 // bugzilla: 60573 - the number of block is not reduced for encryptors
1292
1293                 [Test]
1294                 public void EncryptorWriteBlocks () 
1295                 {
1296                         DebugStream debug = new DebugStream ();
1297
1298                         byte[] key = {0, 1, 2, 3, 4, 5, 6, 7};
1299                         byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7};
1300                         DES des = DES.Create ();
1301                         CryptoStream cse = new CryptoStream (debug, des.CreateEncryptor (key, iv), CryptoStreamMode.Write);
1302
1303                         byte[] data = new byte [64];
1304                         cse.Write (data, 0, 64);
1305                         Assert.AreEqual (64, debug.Length, "Length");
1306                         cse.Close ();
1307                 }
1308
1309                 [Test]
1310                 public void DecryptorWriteBlocks () 
1311                 {
1312                         DebugStream debug = new DebugStream ();
1313
1314                         byte[] key = {0, 1, 2, 3, 4, 5, 6, 7};
1315                         byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7};
1316                         DES des = DES.Create ();
1317                         CryptoStream csd = new CryptoStream (debug, des.CreateDecryptor (key, iv), CryptoStreamMode.Write);
1318
1319                         byte[] data = new byte [64] { 0xE1, 0xB2, 0x46, 0xE5, 0xA7, 0xC7, 0x4C, 0xBC, 0xD5, 0xF0, 0x8E, 0x25, 0x3B, 0xFA, 0x23, 0x80, 0x03, 0x16, 0x18, 0x17, 0xA3, 0x59, 0xBA, 0xAC, 0xFC, 0x47, 0x57, 0x2A, 0xF9, 0x44, 0x07, 0x84, 0x20, 0x74, 0x06, 0x38, 0xC2, 0xF3, 0xA1, 0xCE, 0x8C, 0x73, 0xB1, 0xE3, 0x75, 0x03, 0x66, 0x89, 0xF0, 0x4E, 0x98, 0x68, 0xB1, 0xBD, 0x85, 0x25, 0xFF, 0x4B, 0x11, 0x74, 0xEF, 0x14, 0xC8, 0xE9 };
1320                         csd.Write (data, 0, 64);
1321                         Assert.AreEqual (56, debug.Length, "Length");
1322                         // last block is kept for later processing
1323                 }
1324
1325                 [Test]
1326                 public void PaddingModeNone ()
1327                 {
1328                         byte[] Key = new byte [16];
1329                         byte[] IV = new byte [16];
1330                         byte[] Buffer = new byte [64];
1331
1332                         Rijndael alg = Rijndael.Create ();
1333                         alg.Mode = CipherMode.CBC;
1334                         alg.Padding = PaddingMode.None;
1335
1336                         MemoryStream cms = new MemoryStream ();
1337                         ICryptoTransform ct = alg.CreateDecryptor (Key, IV);
1338                         CryptoStream cs = new CryptoStream (cms, ct, CryptoStreamMode.Write);
1339                         cs.Write (Buffer, 0, 64);
1340                         cs.Close ();
1341
1342                         Assert.AreEqual (64, cms.ToArray ().Length, "Length");
1343                 }
1344
1345                 private void WriteByte (PaddingMode mode, bool padded)
1346                 {
1347                         byte[] Key = new byte[16];
1348                         byte[] IV = new byte[16];
1349                         byte[] Buffer = new byte[64];
1350
1351                         Rijndael alg = Rijndael.Create ();
1352                         alg.Mode = CipherMode.CBC;
1353                         alg.Padding = mode;
1354
1355                         MemoryStream cms = new MemoryStream ();
1356                         ICryptoTransform ct = alg.CreateEncryptor (Key, IV);
1357                         CryptoStream cs = new CryptoStream (cms, ct, CryptoStreamMode.Write);
1358                         for (int i = 0; i < Buffer.Length; i++)
1359                                 cs.WriteByte (Buffer[i]);
1360                         cs.Close ();
1361
1362                         byte[] result = cms.ToArray ();
1363                         // if padded then add one block, if not then it's the original length
1364                         int len = padded ? 80: 64;
1365                         Assert.AreEqual (len, result.Length, mode.ToString () + ".Encrypted.Length");
1366
1367                         cms = new MemoryStream ();
1368                         ct = alg.CreateDecryptor (Key, IV);
1369                         cs = new CryptoStream (cms, ct, CryptoStreamMode.Write);
1370                         for (int i = 0; i < result.Length; i++)
1371                                 cs.WriteByte (result[i]);
1372                         cs.Close ();
1373
1374                         byte[] plaintext = cms.ToArray ();
1375                         Assert.AreEqual (64, plaintext.Length, mode.ToString () + ".Decrypted.Length");
1376
1377                         Assert.AreEqual (Buffer, plaintext, mode.ToString () + ".Date");
1378                 }
1379
1380                 [Test]
1381                 public void WriteByte ()
1382                 {
1383                         WriteByte (PaddingMode.None, false);
1384                         WriteByte (PaddingMode.Zeros, false);
1385                         WriteByte (PaddingMode.PKCS7, true);    // related to bug #81597
1386 #if NET_2_0
1387                         WriteByte (PaddingMode.ANSIX923, true);
1388                         WriteByte (PaddingMode.ISO10126, true);
1389 #endif
1390                 }
1391         }
1392 }