8d306d3e6e2c09f76aa7adfe9a49231bf5238b75
[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                 [Test]
1393                 public void ReadModeDispose_FinalBlock ()
1394                 {
1395                         using (SHA1 sha1 = SHA1.Create()) {
1396                                 using (MemoryStream mem = new MemoryStream(new byte[] { 1, 2, 3 }, false))
1397                                         using (CryptoStream cs = new CryptoStream(mem, sha1, CryptoStreamMode.Read))
1398                                         {
1399                                         }
1400                                 byte b = sha1.Hash [0]; // This will throw if TransformFinalBlock not called in sha1
1401                                 GC.KeepAlive (b); // just the warning...
1402                         }
1403                 }
1404
1405                 [Test]
1406                 public void CustomDisposeCalled ()
1407                 {
1408                         using (MemoryStream mem = new MemoryStream(new byte[] { 1, 2, 3 }, false)) {
1409                                 MyCryptoStream cs;
1410                                 using (cs = new MyCryptoStream (mem, SHA1.Create()))
1411                                 {
1412                                 }
1413                                 Assert.IsTrue (cs.DisposeCalled, "#1");
1414                         }
1415                 }
1416
1417                 [Test]
1418                 public void ExplicitFlush ()
1419                 {
1420                         // Tests that explicitly calling Flush does not call Flush in the underlying stream
1421                         MyStream ms = new MyStream ();
1422                         using (CryptoStream cs = new CryptoStream (ms, SHA1.Create (), CryptoStreamMode.Read)) {
1423                                 ms.FlushCounterEnabled = true;
1424                                 cs.Flush ();
1425                                 ms.FlushCounterEnabled = false;
1426                         }
1427                         Assert.IsTrue (ms.FlushCounter == 0);
1428                 }
1429
1430                 [Test]
1431                 public void ImplicitFlush ()
1432                 {
1433                         // Tests that Dispose() calls Flush on the underlying stream
1434                         MyStream ms = new MyStream ();
1435                         ms.FlushCounterEnabled = true;
1436                         using (CryptoStream cs = new CryptoStream (ms, SHA1.Create (), CryptoStreamMode.Read)) {
1437                         }
1438                         Assert.IsTrue (ms.FlushCounter == 1);
1439                 }
1440
1441                 [Test]
1442                 public void ImplicitFlushCascade ()
1443                 {
1444                         // Tests that Dispose() calls FlushFinalBlock() on the underlying stream
1445                         MyStream ms = new MyStream ();
1446                         ms.FlushCounterEnabled = true;
1447                         CryptoStream cs1 = new CryptoStream (ms, SHA1.Create (), CryptoStreamMode.Read);
1448                         using (CryptoStream cs = new CryptoStream (cs1, SHA1.Create (), CryptoStreamMode.Read)) {
1449                         }
1450                         Assert.IsTrue (ms.FlushCounter == 1);
1451                 }
1452
1453                 [Test]
1454                 [ExpectedException (typeof (ArgumentException))]
1455                 public void Ctor_InvalidEnumValue ()
1456                 {
1457                         CryptoStream cs = new CryptoStream (Stream.Null, SHA1.Create (), (CryptoStreamMode) 0xff);
1458                 }
1459
1460                 class MyCryptoStream : CryptoStream {
1461                         public bool DisposeCalled { get; private set;}
1462
1463                         public MyCryptoStream(Stream stream, ICryptoTransform transform)
1464                                                 : base(stream, transform, CryptoStreamMode.Read)
1465                         {
1466                         }
1467
1468                         protected override void Dispose(bool disposing)
1469                         {
1470                                 base.Dispose(disposing);
1471                                 DisposeCalled = true;
1472                         }
1473                 }
1474
1475                 class ExpandTransform : ICryptoTransform {
1476
1477                         public bool CanReuseTransform {
1478                                 get { return true; }
1479                         }
1480
1481                         public bool CanTransformMultipleBlocks {
1482                                 get; private set;
1483                         }
1484
1485                         public int InputBlockSize {
1486                                 get { return 1; }
1487                         }
1488
1489                         public int OutputBlockSize {
1490                                 get; private set;
1491                         }
1492
1493                         public ExpandTransform (bool canTranformMultipleBlocks, int outputBlockSize)
1494                         {
1495                                 this.CanTransformMultipleBlocks = canTranformMultipleBlocks;
1496                                 this.OutputBlockSize = outputBlockSize;
1497                         }
1498
1499                         public void Dispose ()
1500                         {
1501                         }
1502
1503                         public int TransformBlock (byte [] inputBuffer, int inputOffset, int inputCount, byte [] outputBuffer, int outputOffset)
1504                         {
1505                                 var ret = 0;
1506                                 for (var i = 0; i < inputCount; i++, inputOffset++) {
1507                                         for (var j = 0; j < OutputBlockSize; j++, outputOffset++, ret++) {
1508                                                 outputBuffer [outputOffset] = inputBuffer [inputOffset];
1509                                         }
1510                                 }
1511                                 return ret;
1512                         }
1513
1514                         public byte [] TransformFinalBlock (byte [] inputBuffer, int inputOffset, int inputCount)
1515                         {
1516                                 var outputBuffer = new byte [inputCount * OutputBlockSize];
1517                                 TransformBlock (inputBuffer, inputOffset, inputCount, outputBuffer, 0);
1518                                 return outputBuffer;
1519                         }
1520                 }
1521
1522                 static string[] expand_values = {
1523                         "00-01-02-03-04-05-06-07",
1524                         "00-00-01-01-02-02-03-03-04-04-05-05-06-06-07-07",
1525                         "00-00-00-01-01-01-02-02-02-03-03-03-04-04-04-05-05-05-06-06-06-07-07-07",
1526                         "00-00-00-00-01-01-01-01-02-02-02-02-03-03-03-03-04-04-04-04-05-05-05-05-06-06-06-06-07-07-07-07",
1527                         "00-01-02-03-04-05-06-07",
1528                         "00-00-01-01-02-02-03-03-04-04-05-05-06-06-07-07",
1529                         "00-00-00-01-01-01-02-02-02-03-03-03-04-04-04-05-05-05-06-06-06-07-07-07",
1530                         "00-00-00-00-01-01-01-01-02-02-02-02-03-03-03-03-04-04-04-04-05-05-05-05-06-06-06-06-07-07-07-07"
1531                 };
1532
1533                 [Test]
1534                 public void Expand ()
1535                 {
1536                         int n = 0;
1537                         foreach (var transformMultiple in new [] { false, true }) {
1538                                 foreach (var outputBlockSize in new [] { 1, 2, 3, 4 }) {
1539                                         var expantedStream = new MemoryStream ();
1540                                         var inputData = new byte [] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
1541
1542                                         using (var stream = new CryptoStream (expantedStream, new ExpandTransform (transformMultiple, outputBlockSize), CryptoStreamMode.Write)) {
1543                                                 stream.Write (inputData, 0, inputData.Length);
1544                                         }
1545                                         expantedStream.Close ();
1546
1547                                         string value = BitConverter.ToString (expantedStream.ToArray ());
1548                                         Assert.AreEqual (expand_values [n++], value);
1549                                 }
1550                         }
1551                 }
1552
1553                 class CompressTransform : ICryptoTransform {
1554                         public bool CanReuseTransform {
1555                                 get { return true; }
1556                         }
1557
1558                         public bool CanTransformMultipleBlocks {
1559                                 get { return true; }
1560                         }
1561
1562                         public int InputBlockSize {
1563                                 get; private set;
1564                         }
1565
1566                         public int OutputBlockSize {
1567                                 get { return 1; }
1568                         }
1569
1570                         public CompressTransform (int inputBlockSize)
1571                         {
1572                                 this.InputBlockSize = inputBlockSize;
1573                         }
1574
1575                         public void Dispose ()
1576                         {
1577                         }
1578
1579                         private int bufferedCount = 0;
1580
1581                         public int TransformBlock (byte [] inputBuffer, int inputOffset, int inputCount, byte [] outputBuffer, int outputOffset)
1582                         {
1583                                 var ret = 0;
1584                                 for (var i = 0; i < inputCount; i++, inputOffset++) {
1585                                         if (++bufferedCount == InputBlockSize) {
1586                                                 outputBuffer [outputOffset++] = inputBuffer [inputOffset];
1587                                                 ret++;
1588                                                 bufferedCount = 0;
1589                                         }
1590                                 }
1591                                 return ret;
1592                         }
1593
1594                         public byte [] TransformFinalBlock (byte [] inputBuffer, int inputOffset, int inputCount)
1595                         {
1596                                 var outputBuffer = new byte [inputCount * OutputBlockSize];
1597                                 var ret = TransformBlock (inputBuffer, inputOffset, inputCount, outputBuffer, 0);
1598                                 byte[] result = new byte [ret];
1599                                 Array.Copy (outputBuffer, result, ret);
1600                                 return result;
1601                         }
1602                 }
1603
1604                 static string[] compress_values = {
1605                         "00-01-02-03-04-05-06-07-08-09-0A-0B-0C-0D-0E-0F-10-11-12-13-14-15-16-17-18-19-1A-1B-1C-1D-1E-1F",
1606                         "01-03-05-07-09-0B-0D-0F-11-13-15-17-19-1B-1D-1F",
1607                         "02-05-08-0B-0E-11-14-17-1A-1D",
1608                         "03-07-0B-0F-13-17-1B-1F",
1609                 };
1610
1611                 [Test]
1612                 public void Compress ()
1613                 {
1614                         int n = 0;
1615                         foreach (var inputBlockSize in new [] { 1, 2, 3, 4 }) {
1616                                 var inputData = new byte [] {
1617                                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1618                                         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1619                                         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1620                                         0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
1621                                 };
1622
1623                                 using (var stream = new CryptoStream (new MemoryStream (inputData), new CompressTransform (inputBlockSize), CryptoStreamMode.Read)) {
1624                                         var buffer = new byte [inputData.Length];
1625                                         var ret = stream.Read (buffer, 0, buffer.Length);
1626                                         string value = BitConverter.ToString (buffer, 0, ret);
1627                                         Assert.AreEqual (compress_values [n++], value);
1628                                 }
1629                         }
1630                 }
1631
1632                 class MyStream : Stream {
1633                         public bool FlushCounterEnabled;
1634                         public int FlushCounter;
1635
1636                         public override bool CanRead
1637                         {
1638                                 get {
1639                                         return true;
1640                                 }
1641                         }
1642
1643                         public override bool CanSeek
1644                         {
1645                                 get {
1646                                         return true;
1647                                 }
1648                         }
1649
1650                         public override bool CanWrite
1651                         {
1652                                 get {
1653                                         return true;
1654                                 }
1655                         }
1656
1657                         public override long Length
1658                         {
1659                                 get {
1660                                         return 0;
1661                                 }
1662                         }
1663
1664                         public override long Position
1665                         {
1666                                 get {
1667                                         return 0;
1668                                 }
1669                                 set {
1670                                 }
1671                         }
1672
1673                         public override void Flush ()
1674                         {
1675                                 if (FlushCounterEnabled)
1676                                         FlushCounter++;
1677                         }
1678
1679                         public override int Read (byte[] buffer, int offset, int count)
1680                         {
1681                                 return 0;
1682                         }
1683
1684                         public override int ReadByte ()
1685                         {
1686                                 return -1;
1687                         }
1688
1689                         public override long Seek (long offset, SeekOrigin origin)
1690                         {
1691                                 return 0;
1692                         }
1693
1694                         public override void SetLength (long value)
1695                         {
1696                         }
1697
1698                         public override void Write (byte[] buffer, int offset, int count)
1699                         {
1700                         }
1701
1702                         public override void WriteByte (byte value)
1703                         {
1704                         }
1705                 }
1706         }
1707 }