Merge pull request #249 from pcc/xgetinputfocus
[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 #if !NET_2_1
336                 [Test]
337                 // MS BUG [ExpectedException (typeof (ObjectDisposedException))]
338 #if NET_2_0
339                 [Category ("NotWorking")]
340                 [ExpectedException (typeof (IndexOutOfRangeException))]
341 #else
342                 [Category ("NotDotNet")] // Test cause System.ExecutionEngineException on MS runtime
343                 [ExpectedException (typeof (ArgumentNullException))] // should fail like previous test case
344 #endif
345                 public void Read_Disposed_Break () 
346                 {
347                         // do no corrupt readStream in further tests
348                         using (Stream s = new MemoryStream ()) {
349                                 byte[] buffer = new byte [8];
350                                 cs = new CryptoStream (s, encryptor, CryptoStreamMode.Read);
351                                 int len = cs.Read (buffer, 0, 4);
352                                 Assert.AreEqual (4, len, "Read 4");
353                                 cs.Clear ();
354                                 len = cs.Read (buffer, 3, 4);
355                         }
356                 }
357 #endif
358
359                 [Test]
360                 [ExpectedException (typeof (NotSupportedException))]
361                 public void Read_WriteStream () 
362                 {
363                         cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
364                         byte[] buffer = new byte [8];
365                         cs.Read (buffer, 0, 8);
366                 }
367
368                 [Test]
369                 [ExpectedException (typeof (NullReferenceException))]
370                 public void Read_NullBuffer () 
371                 {
372                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
373                         cs.Read (null, 0, 8);
374                 }
375
376                 [Test]
377                 public void Read_EmptyBuffer_ZeroCount () 
378                 {
379                         byte[] buffer = new byte [0];
380                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
381                         int len = cs.Read (buffer, 0, 0);
382                         Assert.AreEqual (0, len, "Read 0");
383                 }
384
385                 [Test]
386                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
387                 public void Read_NegativeOffset () 
388                 {
389                         byte[] buffer = new byte [8];
390                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
391                         cs.Read (buffer, -1, 8);
392                 }
393
394                 [Test]
395                 public void Read_ZeroCount () 
396                 {
397                         byte[] buffer = new byte [8];
398                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
399                         int len = cs.Read (buffer, 0, 0);
400                         Assert.AreEqual (0, len, "Read 0");
401                 }
402
403                 [Test]
404                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
405                 public void Read_NegativeCount () 
406                 {
407                         byte[] buffer = new byte [8];
408                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
409                         cs.Read (buffer, 0, -1);
410                 }
411
412                 [Test]
413                 [ExpectedException (typeof (ArgumentException))]
414                 public void Read_OverflowCount () 
415                 {
416                         byte[] buffer = new byte [8];
417                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
418                         cs.Read (buffer, 0, Int32.MaxValue);
419                 }
420
421                 [Test]
422                 [ExpectedException (typeof (ArgumentException))]
423                 public void Read_InvalidOffset () 
424                 {
425                         byte[] buffer = new byte [8];
426                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
427                         cs.Read (buffer, 5, 4);
428                 }
429
430                 [Test]
431                 [ExpectedException (typeof (ArgumentException))]
432                 public void Read_OverflowOffset () 
433                 {
434                         byte[] buffer = new byte [8];
435                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
436                         cs.Read (buffer, Int32.MaxValue, 4);
437                 }
438                 
439 #if !NET_2_1
440                 [Test]
441                 // MS BUG [ExpectedException (typeof (ObjectDisposedException))]
442 #if NET_2_0
443                 [Category ("NotWorking")]
444                 [ExpectedException (typeof (IndexOutOfRangeException))]
445 #else
446                 [Category ("NotDotNet")] // Test cause System.ExecutionEngineException on MS runtime
447                 [ExpectedException (typeof (ArgumentNullException))] // to match exception throw by Read in a similar case
448 #endif
449                 public void Write_Disposed () 
450                 {
451                         // do no corrupt writeStream in further tests
452                         using (Stream s = new MemoryStream ()) {
453                                 byte[] buffer = new byte [8];
454                                 cs = new CryptoStream (s, encryptor, CryptoStreamMode.Write);
455                                 cs.Clear ();
456                                 cs.Write (buffer, 0, 8);
457                         }
458                 }
459 #endif
460                 
461                 [Test]
462                 [ExpectedException (typeof (NotSupportedException))]
463                 public void Write_ReadStream () 
464                 {
465                         cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
466                         byte[] buffer = new byte [8];
467                         cs.Write (buffer, 0, 8);
468                 }
469
470                 [Test]
471                 [ExpectedException (typeof (NullReferenceException))]
472                 public void Write_NullBuffer () 
473                 {
474                         cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
475                         cs.Write (null, 0, 8);
476                 }
477
478                 [Test]
479                 public void Write_EmptyBuffer_ZeroCount () 
480                 {
481                         byte[] buffer = new byte [0];
482                         cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
483                         cs.Write (buffer, 0, 0);
484                 }
485
486                 [Test]
487                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
488                 public void Write_NegativeOffset () 
489                 {
490                         byte[] buffer = new byte [8];
491                         cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
492                         cs.Write (buffer, -1, 8);
493                 }
494
495                 [Test]
496                 [ExpectedException (typeof (ArgumentException))]
497                 public void Write_OverflowOffset () 
498                 {
499                         byte[] buffer = new byte [8];
500                         cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
501                         cs.Write (buffer, Int32.MaxValue, 8);
502                 }
503
504                 [Test]
505                 public void Write_ZeroCount () 
506                 {
507                         byte[] buffer = new byte [8];
508                         cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
509                         cs.Write (buffer, 0, 0);
510                 }
511
512                 [Test]
513                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
514                 public void Write_NegativeCount () 
515                 {
516                         byte[] buffer = new byte [8];
517                         cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
518                         cs.Write (buffer, 0, -1);
519                 }
520
521                 [Test]
522                 [ExpectedException (typeof (ArgumentException))]
523                 public void Write_InvalidOffset () 
524                 {
525                         DebugStream debug = new DebugStream ();
526                         byte[] buffer = new byte [8];
527                         cs = new CryptoStream (debug, encryptor, CryptoStreamMode.Write);
528                         cs.Write (buffer, 5, 4);
529                 }
530
531                 [Test]
532                 [ExpectedException (typeof (ArgumentException))]
533                 public void Write_OverflowCount () 
534                 {
535                         DebugStream debug = new DebugStream ();
536                         byte[] buffer = new byte [8];
537                         cs = new CryptoStream (debug, encryptor, CryptoStreamMode.Write);
538                         cs.Write (buffer, 0, Int32.MaxValue);
539                 }
540
541                 [Test]
542                 public void FullRoundtripRead () 
543                 {
544                         byte[] encrypted;
545                         using (DebugStream mem1 = new DebugStream ()) {
546                                 byte[] toEncrypt = Encoding.Unicode.GetBytes ("Please encode me!");
547                                 using (CryptoStream crypt = new CryptoStream (mem1, aes.CreateEncryptor (), CryptoStreamMode.Write)) {
548                                         crypt.Write (toEncrypt, 0, toEncrypt.Length);
549                                         crypt.FlushFinalBlock ();
550                                 }
551                                 encrypted = mem1.ToArray ();
552                         }
553                                         
554                         using (DebugStream mem2 = new DebugStream (encrypted)) {
555                                 byte[] buffer = new byte [1024];
556                                 CryptoStream cr = new CryptoStream (mem2, aes.CreateDecryptor (), CryptoStreamMode.Read);
557                                 int len = cr.Read (buffer, 0, buffer.Length);
558                                 cr.Close ();
559                                 Assert.AreEqual (34, len, "Full Length Read");
560                                 Assert.AreEqual ("Please encode me!", Encoding.Unicode.GetString (buffer, 0, len), "Full Block Read");
561                         }
562                 }
563
564                 // bugzilla 46143 (adapted from test case by Joerg Rosenkranz)
565                 [Test]
566                 public void PartialRoundtripRead () 
567                 {
568                         byte[] encrypted;
569                         using (DebugStream mem1 = new DebugStream ()) {
570                                 byte[] toEncrypt = Encoding.Unicode.GetBytes ("Please encode me!");
571                                 using (CryptoStream crypt = new CryptoStream (mem1, aes.CreateEncryptor (), CryptoStreamMode.Write)) {
572                                         crypt.Write (toEncrypt, 0, toEncrypt.Length);
573                                         crypt.FlushFinalBlock ();
574                                 }
575                                 encrypted = mem1.ToArray ();
576                         }
577                                         
578                         using (DebugStream mem2 = new DebugStream (encrypted)) {
579                                 byte[] buffer = new byte [1024];
580                                 CryptoStream cr = new CryptoStream (mem2, aes.CreateDecryptor (), CryptoStreamMode.Read);
581                                 int len = cr.Read (buffer, 0, 20);
582                                 cr.Clear ();
583                                 cr.Close ();
584                                 Assert.AreEqual (20, len, "Partial Length Read");
585                                 Assert.AreEqual ("Please enc", Encoding.Unicode.GetString (buffer, 0, len), "Partial Block Read");
586                         }
587                 }
588
589                 // bugzilla: 40689 (adapted from test case by Henning Westerholt)
590                 [Test]
591                 public void WriteOnBlockWithFinal () 
592                 {
593                         byte[] desKey = {0, 1, 2, 3, 4, 5, 6, 7};
594                         byte[] desIV = {0, 1, 2, 3, 4, 5, 6, 7};
595                         DES des = DES.Create ();
596
597                         MemoryStream msin = new MemoryStream ();
598                         CryptoStream enc = new CryptoStream (msin, des.CreateEncryptor (desKey, desIV), CryptoStreamMode.Write);
599                         byte[] data = new byte [2200];
600                         enc.Write (data, 0, 2200);
601                         enc.FlushFinalBlock ();
602                         msin.Position = 0;
603                         Assert.AreEqual (2208, msin.Length, "Encryped Write Length"); // 2200 + padding
604
605                         MemoryStream msout = new MemoryStream ();
606                         msout.SetLength (0);
607
608                         byte[] tmp = new byte [1024];
609                         long readlen = 0;
610                         long totallen = msin.Length;
611
612                         CryptoStream dec = new CryptoStream (msout, des.CreateDecryptor (desKey, desIV), CryptoStreamMode.Write);
613                         int len = msin.Read (tmp, 0, 1024);
614                         while (len > 0) {
615                                 dec.Write (tmp, 0, len);
616                                 readlen += len;
617                                 len = msin.Read (tmp, 0, 1024);
618                         }
619                         Assert.AreEqual (2200, msout.Length, "Decryped Write Length");
620
621                         dec.Close ();
622                         dec.Clear ();
623                         msout.Close ();
624                         msin.Close ();
625
626                         Assert.AreEqual (2208, readlen, "Read Length"); // 2200 + padding
627                 }
628
629                 [Test]
630                 public void PreGeneratedStreams ()
631                 {
632                         byte[] desKey = {0, 1, 2, 3, 4, 5, 6, 7};
633                         byte[] desIV = {0, 1, 2, 3, 4, 5, 6, 7};
634                         DES des = DES.Create ();
635         
636                         for (int i=0; i < 9; i++) {
637                                 MemoryStream msin = new MemoryStream ();
638                                 CryptoStream enc = new CryptoStream (msin, des.CreateEncryptor (desKey, desIV), CryptoStreamMode.Write);
639                                 byte[] data = new byte [i];
640                                 enc.Write (data, 0, i);
641                                 enc.FlushFinalBlock ();
642
643                                 string msg = "PreGeneratedStream #" + i;
644                                 string result = BitConverter.ToString (msin.ToArray ());
645                                 switch (i) {
646                                         case 0:
647                                                 Assert.AreEqual ("92-C9-DB-45-30-0B-93-2F", result, msg); 
648                                                 break;
649                                         case 1:
650                                                 Assert.AreEqual ("08-CF-A1-37-BD-56-D0-65", result, msg); 
651                                                 break;
652                                         case 2:
653                                                 Assert.AreEqual ("58-87-D4-9B-2C-27-97-0C", result, msg); 
654                                                 break;
655                                         case 3:
656                                                 Assert.AreEqual ("07-35-90-94-68-7D-51-FB", result, msg); 
657                                                 break;
658                                         case 4:
659                                                 Assert.AreEqual ("BF-00-98-C5-20-71-D0-DB", result, msg); 
660                                                 break;
661                                         case 5:
662                                                 Assert.AreEqual ("1A-55-C8-6E-C1-9B-31-82", result, msg); 
663                                                 break;
664                                         case 6:
665                                                 Assert.AreEqual ("2D-2B-76-41-61-0E-00-0C", result, msg); 
666                                                 break;
667                                         case 7:
668                                                 Assert.AreEqual ("DC-FF-73-D2-7F-D7-48-5D", result, msg); 
669                                                 break;
670                                         case 8:
671                                                 Assert.AreEqual ("E1-B2-46-E5-A7-C7-4C-BC-0E-40-4A-FC-08-92-B1-EB", result, msg); 
672                                                 break;
673                                 }
674                         }
675                 }
676
677                 private byte[] EmptyStream (PaddingMode mode) 
678                 {
679                         SymmetricAlgorithm algo = Rijndael.Create ();
680                         algo.Key = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
681                         algo.IV = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
682                         algo.Padding = mode;
683                         MemoryStream ms = new MemoryStream ();
684                         CryptoStream cs = new CryptoStream (ms, algo.CreateEncryptor(), CryptoStreamMode.Write);
685                         cs.Write (ms.GetBuffer (), 0, (int) ms.Length);
686                         cs.FlushFinalBlock ();
687                         cs.Flush ();
688                         return ms.ToArray ();
689                 }
690
691                 [Test]
692                 public void EmptyStreamWithPaddingNone () 
693                 {
694                         byte[] result = EmptyStream (PaddingMode.None);
695                         Assert.AreEqual (0, result.Length, "Result Length");
696                 }
697
698                 [Test]
699                 public void EmptyStreamWithPaddingPKCS7 () 
700                 {
701                         byte[] expected = { 0x07, 0xFE, 0xEF, 0x74, 0xE1, 0xD5, 0x03, 0x6E, 0x90, 0x0E, 0xEE, 0x11, 0x8E, 0x94, 0x92, 0x93 };
702                         byte[] result = EmptyStream (PaddingMode.PKCS7);
703                         Assert.AreEqual (16, result.Length, "Result Length");
704                         Assert.AreEqual (expected, result, "Result");
705                 }
706
707                 [Test]
708                 public void EmptyStreamWithPaddingZeros () 
709                 {
710                         byte[] result = EmptyStream (PaddingMode.Zeros);
711                         Assert.AreEqual (0, result.Length, "Result Length");
712                 }
713
714                 // bugzilla: 49323 (adapted from test case by Carlos Guzmán Álvarez)
715                 [Test]
716                 public void MultiblocksWithPartial () 
717                 {
718                         SymmetricAlgorithm tdes = new TripleDESCryptoServiceProvider ();
719                         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};
720                         tdes.IV = new byte[] {193, 227, 54, 132, 68, 172, 55, 91};
721
722                         byte[] fragment = new byte[] {20, 0, 0, 12, 181, 134, 8, 230, 185, 75, 19, 129, 101, 142, 118, 190};
723                         byte[] mac = new byte[] {42, 148, 229, 58, 185, 249, 154, 131, 157, 79, 176, 168, 143, 71, 0, 118, 5, 10, 95, 8};
724                                                                                                                                                                                                   
725                         // Encryption ( fragment + mac [+ padding + padding_length] )
726                         MemoryStream ms = new MemoryStream ();
727                         CryptoStream cs = new CryptoStream (ms, tdes.CreateEncryptor (), CryptoStreamMode.Write);
728                         cs.Write (fragment, 0, fragment.Length);
729                         cs.Write (mac, 0, mac.Length);
730                         // Calculate padding_length
731                         int fragmentLength = fragment.Length + mac.Length + 1;
732                         int padding = (((fragmentLength / 8) * 8) + 8) - fragmentLength;
733                         // Write padding length byte
734                         cs.WriteByte ((byte)padding);
735                         cs.Close ();
736                         byte[] encrypted = ms.ToArray ();
737                         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 };
738                         Assert.AreEqual (expected, encrypted, "MultiblocksWithPartial");
739                 }
740
741                 // Adapted from Subba Rao Thirumoorthy email on mono-devel-list (december 2003)
742                 private byte[] NonMultipleOfBlockSize_Encrypt (ICryptoTransform ct, byte[] data)
743                 {
744                         DebugStream stream = new DebugStream ();
745                         CryptoStream CryptStream = new CryptoStream (stream, ct, CryptoStreamMode.Write);
746
747                         int len = 0;
748                         long myLength = 0;
749                         byte[] Buffer = new byte [1024];
750                         
751                         DebugStream fout = new DebugStream (data);
752                         while (myLength < data.Length) {
753                                 len = fout.Read (Buffer, 0, 1023);
754                                 if (len == 0)
755                                         break;
756                                 CryptStream.Write (Buffer, 0, len);
757                                 CryptStream.Flush ();
758                                 myLength = myLength + len;
759                         }
760                         CryptStream.FlushFinalBlock ();
761                         // we must ensure that the result is correct
762                         Assert.AreEqual (64, len, "Length(final)");
763                         byte[] result = stream.ToArray ();
764                         string end = BitConverter.ToString (result, 65520, 16);
765                         Assert.AreEqual ("04-70-19-1D-28-C5-BD-9A-23-C6-60-E2-28-96-38-65", end, "End part");
766
767                         CryptStream.Close();
768                         stream.Close();
769                         return result;
770                 }
771
772                 private byte[] NonMultipleOfBlockSize_Decrypt (ICryptoTransform ct, byte[] data) 
773                 {
774                         DebugStream stream = new DebugStream (data);
775                         CryptoStream CryptStream = new CryptoStream (stream, ct, CryptoStreamMode.Read);
776
777                         int len = 0;
778                         long myLength = 0;
779                         byte[] Buffer = new Byte [1024];
780
781                         DebugStream fout = new DebugStream ();
782                         // each returned block must be 1023 bytes long 
783                         // even if this isn't a multiple of the block size
784                         while ((len = CryptStream.Read (Buffer, 0, 1023)) != 0) {
785                                 fout.Write (Buffer, 0, len);
786                                 fout.Flush ();
787                                 myLength = myLength + len;
788                         }
789
790                         byte[] result = fout.ToArray ();
791                         CryptStream.Close ();
792                         stream.Close ();
793                         return result;
794                 }
795
796                 [Test]
797                 public void NonMultipleOfBlockSize ()
798                 {
799                         byte[] key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
800                         byte[] iv  = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 };
801                         byte[] data = new byte [65536];
802
803                         RijndaelManaged aes = new RijndaelManaged ();
804                         ICryptoTransform encryptor = aes.CreateEncryptor (key, iv);
805                         byte[] encdata = NonMultipleOfBlockSize_Encrypt (encryptor, data);
806                         Assert.AreEqual ((data.Length + (aes.BlockSize >> 3)), encdata.Length, "Encrypted Data Length");
807                         
808                         ICryptoTransform decryptor = aes.CreateDecryptor (key, iv);
809                         byte[] decdata = NonMultipleOfBlockSize_Decrypt (decryptor, encdata);
810                         Assert.AreEqual (data.Length, decdata.Length, "Decrypted Data Length");
811
812                         int i = 0;
813                         bool b = true;
814                         while (b && (i < data.Length)) {
815                                 b = (data [i] == decdata [i]);
816                                 i++;
817                         }
818                         Assert.IsTrue (b, "NonMultipleOfBlockSize");
819                 }
820
821                 // bugzilla: 51322 - indirectly related but it explains why my first (unapplied) patch didn't work
822                 [Test]
823                 public void DecryptPartial_TransformFinalBlock_required () 
824                 {
825                         byte[] key = {0, 1, 2, 3, 4, 5, 6, 7};
826                         byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7};
827                         DES des = DES.Create ();
828
829                         byte[] data = Encoding.Unicode.GetBytes ("ximian");     // 12 bytes, 1.5 DES block size
830                         DebugStream encrypted = new DebugStream ();
831                         cs = new CryptoStream (encrypted, des.CreateEncryptor (key, iv), CryptoStreamMode.Write);
832                         cs.Write (data, 0, data.Length);
833                         cs.Close ();
834
835                         data = encrypted.ToArray ();
836                         DebugStream decrypted = new DebugStream (data);
837                         cs = new CryptoStream (decrypted, des.CreateDecryptor (key, iv), CryptoStreamMode.Read);
838                         int len = cs.Read (data, 0, data.Length);
839                         cs.Close ();
840                         Assert.AreEqual (12, len, "Length");
841                         Assert.AreEqual ("ximian", Encoding.Unicode.GetString (data, 0, len), "Unicode DES Roundtrip");
842                 }
843
844 #if NET_2_0
845                 [Category ("NotWorking")]
846 #endif          
847                 [Test]
848                 public void DecryptPartial_TransformFinalBlock_2Pass () 
849                 {
850                         byte[] key = {0, 1, 2, 3, 4, 5, 6, 7};
851                         byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7};
852                         DES des = DES.Create ();
853
854                         byte[] data = Encoding.Unicode.GetBytes ("ximian");     // 12 bytes, 1.5 DES block size
855                         DebugStream encrypted = new DebugStream ();
856                         cs = new CryptoStream (encrypted, des.CreateEncryptor (key, iv), CryptoStreamMode.Write);
857                         cs.Write (data, 0, data.Length);
858                         cs.Close ();
859
860                         data = encrypted.ToArray ();
861                         DebugStream decrypted = new DebugStream (data);
862                         cs = new CryptoStream (decrypted, des.CreateDecryptor (key, iv), CryptoStreamMode.Read);
863                         int len = cs.Read (data, 0, 6);
864                         Assert.AreEqual (6, len, "Length (1st pass)");
865                         Assert.AreEqual ("xim", Encoding.Unicode.GetString (data, 0, len), "Partial DES Roundtrip");
866                         len += cs.Read (data, 6, 8);
867                         Assert.AreEqual (12, len, "Length (1st+2nd)");
868                         Assert.AreEqual ("ximian", Encoding.Unicode.GetString (data, 0, len), "Full DES Roundtrip");
869                         cs.Close ();
870                 }
871
872                 // based on http://www.c-sharpcorner.com/Code/2002/May/FileEncryption.asp
873 #if NET_2_0
874                 [Category ("NotWorking")]
875 #endif  
876                 [Test]
877                 public void WriteByteReadByte () 
878                 {
879                         DebugStream original = new DebugStream (Encoding.Unicode.GetBytes ("ximian"));
880
881                         DebugStream encrypted = new DebugStream ();
882                         byte[] key = {0, 1, 2, 3, 4, 5, 6, 7};
883                         byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7};
884                         DES des = DES.Create ();
885                         cs = new CryptoStream (encrypted, des.CreateEncryptor (key, iv), CryptoStreamMode.Write);
886
887                         int data;
888                         while ((data = original.ReadByte ()) != -1)
889                                 cs.WriteByte((byte) data);
890                         cs.Close ();
891
892                         byte[] result = encrypted.ToArray ();
893                         Assert.AreEqual ("18-EA-93-3F-20-86-D2-AA-78-02-D7-6F-E4-47-17-9C", BitConverter.ToString (result), "Encrypted");
894
895                         encrypted = new DebugStream (result);
896                         DebugStream decrypted = new DebugStream ();
897                         cs = new CryptoStream (encrypted, des.CreateDecryptor (key, iv), CryptoStreamMode.Read);
898
899                         while ((data = cs.ReadByte ()) != -1)
900                                 decrypted.WriteByte((byte) data);
901                         cs.Close ();
902                         decrypted.Close ();
903
904                         Assert.AreEqual ("ximian", Encoding.Unicode.GetString (decrypted.ToArray ()), "W/R Byte Roundtrip");
905                 }
906
907                 // based http://www.4guysfromrolla.com/webtech/090501-1.shtml
908
909                 public string EncryptData (ICryptoTransform des, string strData) 
910                 {
911                         strData = String.Format("{0,5:00000}" + strData, strData.Length);
912                         byte[] data = Encoding.ASCII.GetBytes (strData);
913
914                         MemoryStream mStream = new MemoryStream (data); 
915                         CryptoStream cs = new CryptoStream (mStream, des, CryptoStreamMode.Read);        
916                         MemoryStream mOut = new MemoryStream ();
917         
918                         int bytesRead; 
919                         byte[] output = new byte [1024]; 
920                         do { 
921                                 bytesRead = cs.Read (output, 0, 1024);
922                                 if (bytesRead != 0) 
923                                         mOut.Write (output, 0, bytesRead); 
924                         } 
925                         while (bytesRead > 0); 
926         
927                         return Convert.ToBase64String (mOut.ToArray ());
928                 }
929
930                 public string DecryptData (ICryptoTransform des, string strData) 
931                 {
932                         MemoryStream mOut = new MemoryStream ();
933                         byte[] data = Convert.FromBase64String (strData);
934                         CryptoStream cs = new CryptoStream (mOut, des, CryptoStreamMode.Write);        
935                         cs.Write (data, 0, (int)data.Length);
936                         cs.FlushFinalBlock ();
937                         return Encoding.ASCII.GetString (mOut.ToArray ()).Substring (5);
938                 }
939
940                 [Test]
941                 public void EncryptOnRead () 
942                 {
943                         SHA1 sha = SHA1.Create ();
944                         byte[] vector = sha.ComputeHash (Encoding.ASCII.GetBytes ("s3kr3t"));
945                         byte[] key = new byte [8];
946                         Buffer.BlockCopy (vector, 0, key, 0, key.Length);
947                         byte[] iv = new byte [8];
948                         Buffer.BlockCopy (vector, 8, iv, 0, iv.Length);
949
950                         DES des = DES.Create ();
951
952                         StringBuilder sb = new StringBuilder ();
953                         sb.Append ("a");
954                         string data = sb.ToString ();
955                         string encdata = EncryptData (des.CreateEncryptor (key, iv), data);
956                         string decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
957                         Assert.AreEqual ("9YVfvrh5yj0=", encdata, "Encrypt-" + data);
958                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
959
960                         sb.Append ("a");
961                         data = sb.ToString ();
962                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
963                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
964                         Assert.AreEqual ("qNe4d0UlkU8=", encdata, "Encrypt-" + data);
965                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
966
967                         sb.Append ("a");
968                         data = sb.ToString ();
969                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
970                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
971                         Assert.AreEqual ("OcernYAQ1NAME/Gny+ZuaA==", encdata, "Encrypt-" + data);
972                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
973
974                         sb.Append ("a");
975                         data = sb.ToString ();
976                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
977                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
978                         Assert.AreEqual ("H5UveR2lds1T+IWN4pks2Q==", encdata, "Encrypt-" + data);
979                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
980
981                         sb.Append ("a");
982                         data = sb.ToString ();
983                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
984                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
985                         Assert.AreEqual ("dDQ3HAVtTbiRwwUqWANaeA==", encdata, "Encrypt-" + data);
986                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
987
988                         sb.Append ("a");
989                         data = sb.ToString ();
990                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
991                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
992                         Assert.AreEqual ("At1r7dVDjJlQidf4QzCNkw==", encdata, "Encrypt-" + data);
993                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
994
995                         sb.Append ("a");
996                         data = sb.ToString ();
997                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
998                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
999                         Assert.AreEqual ("DFDJWJGaNrFVBDXovsq1ew==", encdata, "Encrypt-" + data);
1000                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1001
1002                         sb.Append ("a");
1003                         data = sb.ToString ();
1004                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1005                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1006                         Assert.AreEqual ("gM040QGMPOBj3u1lEK4XHQ==", encdata, "Encrypt-" + data);
1007                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1008
1009                         sb.Append ("a");
1010                         data = sb.ToString ();
1011                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1012                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1013                         Assert.AreEqual ("P5hRUhrxOWFX0ER/IjJL/Q==", encdata, "Encrypt-" + data);
1014                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1015
1016                         sb.Append ("a");
1017                         data = sb.ToString ();
1018                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1019                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1020                         Assert.AreEqual ("uDIaQ1uXtWUIboGFLt306Q==", encdata, "Encrypt-" + data);
1021                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1022
1023                         sb.Append ("a");
1024                         data = sb.ToString ();
1025                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1026                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1027                         Assert.AreEqual ("giJKTXfad5Z8hebhXtYZ4hmKX/EC8w6x", encdata, "Encrypt-" + data);
1028                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1029
1030                         sb.Append ("a");
1031                         data = sb.ToString ();
1032                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1033                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1034                         Assert.AreEqual ("lBehBplIrjjrlIrMjYcNz1DOoXLHjZdn", encdata, "Encrypt-" + data);
1035                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1036
1037                         sb.Append ("a");
1038                         data = sb.ToString ();
1039                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1040                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1041                         Assert.AreEqual ("2elWrUnjmsAOpo2s4voJyZXEJ/rtKB7P", encdata, "Encrypt-" + data);
1042                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1043
1044                         sb.Append ("a");
1045                         data = sb.ToString ();
1046                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1047                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1048                         Assert.AreEqual ("GB3BaIZGf9K+T82j7T8Fri2rQ2/YUdSe", encdata, "Encrypt-" + data);
1049                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1050
1051                         sb.Append ("a");
1052                         data = sb.ToString ();
1053                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1054                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1055                         Assert.AreEqual ("Gc+wkJL+CVjdJchgcIoi8dkH2BVpHJgB", encdata, "Encrypt-" + data);
1056                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1057
1058                         sb.Append ("a");
1059                         data = sb.ToString ();
1060                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1061                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1062                         Assert.AreEqual ("loeuyII/PvWb91M4pFVkyaPxQoQVYpNb", encdata, "Encrypt-" + data);
1063                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1064
1065                         sb.Append ("a");
1066                         data = sb.ToString ();
1067                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1068                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1069                         Assert.AreEqual ("PHXmi/sxNIgApXAfdm+Bf54/nCM//N8o", encdata, "Encrypt-" + data);
1070                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1071
1072                         sb.Append ("a");
1073                         data = sb.ToString ();
1074                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1075                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1076                         Assert.AreEqual ("xpb+wj/8LmH2ScTg3OU4JOsE5Owj6flF", encdata, "Encrypt-" + data);
1077                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1078
1079                         sb.Append ("a");
1080                         data = sb.ToString ();
1081                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1082                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1083                         Assert.AreEqual ("WJz4VfsZ2emzhYWoSf+PNBDpHooxEregqMWnzm4gcqU=", encdata, "Encrypt-" + data);
1084                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1085
1086                         sb.Append ("a");
1087                         data = sb.ToString ();
1088                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1089                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1090                         Assert.AreEqual ("PaouZu1iOKbCMRJSu04y/kB+TcOk4yp8K2BOGDs1PPE=", encdata, "Encrypt-" + data);
1091                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1092
1093                         sb.Append ("a");
1094                         data = sb.ToString ();
1095                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1096                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1097                         Assert.AreEqual ("qbTDs4dFy7eERdn5vV7JRPk2/m9smtwvZjA6+TmGlkI=", encdata, "Encrypt-" + data);
1098                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1099
1100                         sb.Append ("a");
1101                         data = sb.ToString ();
1102                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1103                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1104                         Assert.AreEqual ("f2FsphcpM7Fu90S5V17ptly44lL4GvFCCaFdnnU4twk=", encdata, "Encrypt-" + data);
1105                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1106
1107                         sb.Append ("a");
1108                         data = sb.ToString ();
1109                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1110                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1111                         Assert.AreEqual ("imD+ntHsUmp9ALJedzC1JmAJY0r2O4KkP8271+XuG4g=", encdata, "Encrypt-" + data);
1112                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1113
1114                         sb.Append ("a");
1115                         data = sb.ToString ();
1116                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1117                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1118                         Assert.AreEqual ("80QLLUmHwx1fcEYGeFz1WXlS13kUy994sQLI6GhcjuM=", encdata, "Encrypt-" + data);
1119                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1120
1121                         sb.Append ("a");
1122                         data = sb.ToString ();
1123                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1124                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1125                         Assert.AreEqual ("DtIIlj8BCOppmIgQ9AEdUj7pBB49S/9Q38kbWLjwiVs=", encdata, "Encrypt-" + data);
1126                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1127
1128                         sb.Append ("a");
1129                         data = sb.ToString ();
1130                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1131                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1132                         Assert.AreEqual ("LNkprYaaUFtyan204OzX+a2pzOb/Pg5WXzXJ6WWB1rQ=", encdata, "Encrypt-" + data);
1133                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1134
1135                         sb.Append ("a");
1136                         data = sb.ToString ();
1137                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1138                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1139                         Assert.AreEqual ("FRgx9m2lT2PxtYSIdRwc+SznJetNiRk1MEIZDl3D13pvo2yOtJ1MSQ==", encdata, "Encrypt-" + data);
1140                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1141
1142                         sb.Append ("a");
1143                         data = sb.ToString ();
1144                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1145                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1146                         Assert.AreEqual ("V7JlnpJscrdIpX4z5S+/Q5WDjKzK4aB5TiqI3JZOYJ+KE1CWQNNeow==", encdata, "Encrypt-" + data);
1147                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1148
1149                         sb.Append ("a");
1150                         data = sb.ToString ();
1151                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1152                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1153                         Assert.AreEqual ("wVwPv1c2KQynbwiOBCAhmQlReOQT52qFR34AX4dtjEeQ1oCQ1N1tHg==", encdata, "Encrypt-" + data);
1154                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1155
1156                         sb.Append ("a");
1157                         data = sb.ToString ();
1158                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1159                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1160                         Assert.AreEqual ("Zi+G0yfmuFjSjP455pjVeKBDDWB4qvTb0K0h20UtflrYG6wcWqUzDw==", encdata, "Encrypt-" + data);
1161                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1162
1163                         sb.Append ("a");
1164                         data = sb.ToString ();
1165                         encdata = EncryptData (des.CreateEncryptor (key, iv), data);
1166                         decdata = DecryptData (des.CreateDecryptor (key, iv), encdata);
1167                         Assert.AreEqual ("0hGoonZ8jrLhMNDKBuWrlvFnq15ZLvnyq+Ilq8r4aYUEDxttQMwi5w==", encdata, "Encrypt-" + data);
1168                         Assert.AreEqual (data, decdata, "Decrypt-" + data);
1169                 }
1170
1171                 // based on System.Security assembly XmlDsigBase64TransformTest
1172
1173                 [Test]
1174                 public void FromBase64_Write () 
1175                 {
1176                         string expected = "http://www.go-mono.com/";
1177                         byte[] data = Encoding.UTF8.GetBytes (expected);
1178                         string temp = Convert.ToBase64String (data, 0, data.Length);
1179                         data = Encoding.UTF8.GetBytes (temp);
1180
1181                         DebugStream debug = new DebugStream ();
1182                         ICryptoTransform base64 = new FromBase64Transform ();
1183                         cs = new CryptoStream (debug, base64, CryptoStreamMode.Write);
1184                         cs.Write (data, 0, data.Length);
1185                         cs.FlushFinalBlock ();
1186                         byte[] encoded = debug.ToArray ();
1187
1188                         string result = Encoding.UTF8.GetString (encoded);
1189                         Assert.AreEqual (expected, result, "FromBase64_Write");
1190                 }
1191
1192                 [Test]
1193                 public void FromBase64_Read () 
1194                 {
1195                         byte[] original = Encoding.UTF8.GetBytes ("aHR0cDovL3d3dy5nby1tb25vLmNvbS8=");
1196                         DebugStream debug = new DebugStream (original);
1197
1198                         ICryptoTransform base64 = new FromBase64Transform ();
1199                         cs = new CryptoStream (debug, base64, CryptoStreamMode.Read);
1200                         
1201                         byte[] data = new byte [1024];
1202                         int length = cs.Read (data, 0, data.Length);
1203                         cs.Close ();
1204
1205                         string result = Encoding.UTF8.GetString (data, 0, length);
1206                         Assert.AreEqual ("http://www.go-mono.com/", result, "ToBase64_Read");
1207                 }
1208
1209                 [Test]
1210                 public void ToBase64_Write () 
1211                 {
1212                         byte[] data = Encoding.UTF8.GetBytes ("http://www.go-mono.com/");
1213
1214                         DebugStream debug = new DebugStream ();
1215                         ICryptoTransform base64 = new ToBase64Transform ();
1216                         cs = new CryptoStream (debug, base64, CryptoStreamMode.Write);
1217                         cs.Write (data, 0, data.Length);
1218                         cs.FlushFinalBlock ();
1219                         byte[] encoded = debug.ToArray ();
1220
1221                         string result = Encoding.UTF8.GetString (encoded);
1222                         Assert.AreEqual ("aHR0cDovL3d3dy5nby1tb25vLmNvbS8=", result, "ToBase64_Write");
1223                 }
1224
1225                 [Test]
1226                 public void ToBase64_Read () 
1227                 {
1228                         byte[] original = Encoding.UTF8.GetBytes ("http://www.go-mono.com/");
1229                         DebugStream debug = new DebugStream (original);
1230
1231                         ICryptoTransform base64 = new ToBase64Transform ();
1232                         cs = new CryptoStream (debug, base64, CryptoStreamMode.Read);
1233                         
1234                         byte[] data = new byte [1024];
1235                         int length = cs.Read (data, 0, data.Length);
1236                         cs.Close ();
1237
1238                         string result = Encoding.UTF8.GetString (data, 0, length);
1239                         Assert.AreEqual ("aHR0cDovL3d3dy5nby1tb25vLmNvbS8=", result, "ToBase64_Read");
1240                 }
1241
1242                 // Cascaded CryptoStream - like sample in book .NET Framework Security, chapter 30
1243
1244                 [Test]
1245                 public void CascadedCryptoStream_Write () 
1246                 {
1247                         DebugStream debug = new DebugStream ();
1248
1249                         // calculate both the hash (before encryption) and encrypt in one Write operation
1250                         byte[] key = {0, 1, 2, 3, 4, 5, 6, 7};
1251                         byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7};
1252                         DES des = DES.Create ();
1253                         CryptoStream cse = new CryptoStream (debug, des.CreateEncryptor (key, iv), CryptoStreamMode.Write);
1254
1255                         MD5 hash = MD5.Create ();
1256                         CryptoStream csh = new CryptoStream (cse, hash, CryptoStreamMode.Write);
1257
1258                         byte[] data = Encoding.UTF8.GetBytes ("http://www.go-mono.com/");
1259                         csh.Write (data, 0, data.Length);
1260                         csh.FlushFinalBlock ();
1261
1262                         byte[] result = debug.ToArray ();
1263                         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");
1264                         byte[] digest = hash.Hash;
1265                         Assert.AreEqual ("71-04-12-D1-95-01-CF-F9-8D-8F-F8-0D-F9-AA-11-7D", BitConverter.ToString (digest), "Hash");
1266                 }
1267 #if NET_2_0
1268                 [Category ("NotWorking")]
1269 #endif  
1270                 [Test]
1271                 public void CascadedCryptoStream_Read () 
1272                 {
1273                         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 };
1274                         DebugStream debug = new DebugStream (encdata);
1275
1276                         // decrypt data and validate its hash in one Read operation
1277                         byte[] key = {0, 1, 2, 3, 4, 5, 6, 7};
1278                         byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7};
1279                         DES des = DES.Create ();
1280                         CryptoStream csd = new CryptoStream (debug, des.CreateDecryptor (key, iv), CryptoStreamMode.Read);
1281
1282                         MD5 hash = MD5.Create ();
1283                         CryptoStream csh = new CryptoStream (csd, hash, CryptoStreamMode.Read);
1284
1285                         byte[] data = new byte [1024];
1286                         int length = csh.Read (data, 0, data.Length);
1287                         csh.Close ();
1288                         
1289                         string result = Encoding.UTF8.GetString (data, 0, length);
1290                         Assert.AreEqual ("http://www.go-mono.com/", result, "Decrypted");
1291                         byte[] digest = hash.Hash;
1292                         Assert.AreEqual ("71-04-12-D1-95-01-CF-F9-8D-8F-F8-0D-F9-AA-11-7D", BitConverter.ToString (digest), "Hash Validation");
1293                 }
1294
1295                 // bugzilla: 60573 - the number of block is not reduced for encryptors
1296
1297                 [Test]
1298                 public void EncryptorWriteBlocks () 
1299                 {
1300                         DebugStream debug = new DebugStream ();
1301
1302                         byte[] key = {0, 1, 2, 3, 4, 5, 6, 7};
1303                         byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7};
1304                         DES des = DES.Create ();
1305                         CryptoStream cse = new CryptoStream (debug, des.CreateEncryptor (key, iv), CryptoStreamMode.Write);
1306
1307                         byte[] data = new byte [64];
1308                         cse.Write (data, 0, 64);
1309                         Assert.AreEqual (64, debug.Length, "Length");
1310                         cse.Close ();
1311                 }
1312
1313                 [Test]
1314                 public void DecryptorWriteBlocks () 
1315                 {
1316                         DebugStream debug = new DebugStream ();
1317
1318                         byte[] key = {0, 1, 2, 3, 4, 5, 6, 7};
1319                         byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7};
1320                         DES des = DES.Create ();
1321                         CryptoStream csd = new CryptoStream (debug, des.CreateDecryptor (key, iv), CryptoStreamMode.Write);
1322
1323                         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 };
1324                         csd.Write (data, 0, 64);
1325                         Assert.AreEqual (56, debug.Length, "Length");
1326                         // last block is kept for later processing
1327                 }
1328
1329                 [Test]
1330                 public void PaddingModeNone ()
1331                 {
1332                         byte[] Key = new byte [16];
1333                         byte[] IV = new byte [16];
1334                         byte[] Buffer = new byte [64];
1335
1336                         Rijndael alg = Rijndael.Create ();
1337                         alg.Mode = CipherMode.CBC;
1338                         alg.Padding = PaddingMode.None;
1339
1340                         MemoryStream cms = new MemoryStream ();
1341                         ICryptoTransform ct = alg.CreateDecryptor (Key, IV);
1342                         CryptoStream cs = new CryptoStream (cms, ct, CryptoStreamMode.Write);
1343                         cs.Write (Buffer, 0, 64);
1344                         cs.Close ();
1345
1346                         Assert.AreEqual (64, cms.ToArray ().Length, "Length");
1347                 }
1348
1349                 private void WriteByte (PaddingMode mode, bool padded)
1350                 {
1351                         byte[] Key = new byte[16];
1352                         byte[] IV = new byte[16];
1353                         byte[] Buffer = new byte[64];
1354
1355                         Rijndael alg = Rijndael.Create ();
1356                         alg.Mode = CipherMode.CBC;
1357                         alg.Padding = mode;
1358
1359                         MemoryStream cms = new MemoryStream ();
1360                         ICryptoTransform ct = alg.CreateEncryptor (Key, IV);
1361                         CryptoStream cs = new CryptoStream (cms, ct, CryptoStreamMode.Write);
1362                         for (int i = 0; i < Buffer.Length; i++)
1363                                 cs.WriteByte (Buffer[i]);
1364                         cs.Close ();
1365
1366                         byte[] result = cms.ToArray ();
1367                         // if padded then add one block, if not then it's the original length
1368                         int len = padded ? 80: 64;
1369                         Assert.AreEqual (len, result.Length, mode.ToString () + ".Encrypted.Length");
1370
1371                         cms = new MemoryStream ();
1372                         ct = alg.CreateDecryptor (Key, IV);
1373                         cs = new CryptoStream (cms, ct, CryptoStreamMode.Write);
1374                         for (int i = 0; i < result.Length; i++)
1375                                 cs.WriteByte (result[i]);
1376                         cs.Close ();
1377
1378                         byte[] plaintext = cms.ToArray ();
1379                         Assert.AreEqual (64, plaintext.Length, mode.ToString () + ".Decrypted.Length");
1380
1381                         Assert.AreEqual (Buffer, plaintext, mode.ToString () + ".Date");
1382                 }
1383
1384                 [Test]
1385                 public void WriteByte ()
1386                 {
1387                         WriteByte (PaddingMode.None, false);
1388                         WriteByte (PaddingMode.Zeros, false);
1389                         WriteByte (PaddingMode.PKCS7, true);    // related to bug #81597
1390 #if NET_2_0
1391                         WriteByte (PaddingMode.ANSIX923, true);
1392                         WriteByte (PaddingMode.ISO10126, true);
1393 #endif
1394                 }
1395
1396                 [Test]
1397                 public void ReadModeDispose_FinalBlock ()
1398                 {
1399                         using (SHA1 sha1 = SHA1.Create()) {
1400                                 using (MemoryStream mem = new MemoryStream(new byte[] { 1, 2, 3 }, false))
1401                                         using (CryptoStream cs = new CryptoStream(mem, sha1, CryptoStreamMode.Read))
1402                                         {
1403                                         }
1404                                 byte b = sha1.Hash [0]; // This will throw if TransformFinalBlock not called in sha1
1405                                 GC.KeepAlive (b); // just the warning...
1406                         }
1407                 }
1408
1409                 [Test]
1410                 public void CustomDisposeCalled ()
1411                 {
1412                         using (MemoryStream mem = new MemoryStream(new byte[] { 1, 2, 3 }, false)) {
1413                                 MyCryptoStream cs;
1414                                 using (cs = new MyCryptoStream (mem, SHA1.Create()))
1415                                 {
1416                                 }
1417                                 Assert.IsTrue (cs.DisposeCalled, "#1");
1418                         }
1419                 }
1420
1421                 [Test]
1422                 public void ExplicitFlush ()
1423                 {
1424                         // Tests that explicitly calling Flush does not call Flush in the underlying stream
1425                         MyStream ms = new MyStream ();
1426                         using (CryptoStream cs = new CryptoStream (ms, SHA1.Create (), CryptoStreamMode.Read)) {
1427                                 ms.FlushCounterEnabled = true;
1428                                 cs.Flush ();
1429                                 ms.FlushCounterEnabled = false;
1430                         }
1431                         Assert.IsTrue (ms.FlushCounter == 0);
1432                 }
1433
1434                 [Test]
1435                 public void ImplicitFlush ()
1436                 {
1437                         // Tests that Dispose() calls Flush on the underlying stream
1438                         MyStream ms = new MyStream ();
1439                         ms.FlushCounterEnabled = true;
1440                         using (CryptoStream cs = new CryptoStream (ms, SHA1.Create (), CryptoStreamMode.Read)) {
1441                         }
1442                         Assert.IsTrue (ms.FlushCounter == 1);
1443                 }
1444
1445                 [Test]
1446                 public void ImplicitFlushCascade ()
1447                 {
1448                         // Tests that Dispose() calls FlushFinalBlock() on the underlying stream
1449                         MyStream ms = new MyStream ();
1450                         ms.FlushCounterEnabled = true;
1451                         CryptoStream cs1 = new CryptoStream (ms, SHA1.Create (), CryptoStreamMode.Read);
1452                         using (CryptoStream cs = new CryptoStream (cs1, SHA1.Create (), CryptoStreamMode.Read)) {
1453                         }
1454                         Assert.IsTrue (ms.FlushCounter == 1);
1455                 }
1456
1457                 [Test]
1458                 [ExpectedException (typeof (ArgumentException))]
1459                 public void Ctor_InvalidEnumValue ()
1460                 {
1461                         CryptoStream cs = new CryptoStream (Stream.Null, SHA1.Create (), (CryptoStreamMode) 0xff);
1462                 }
1463
1464                 [Test]
1465                 public void OutputBlock_Smaller ()
1466                 {
1467                         // The OutputBlockSize is smaller than the InputBlockSize
1468                         using (CryptoStream cs = new CryptoStream(Stream.Null, new MyCryptAlgorithm(), CryptoStreamMode.Write)) {
1469                                 byte[] buffer = new byte[512 * 1024];
1470                                 cs.Write(buffer, 0, buffer.Length);
1471                         }
1472                 }
1473
1474                 class MyCryptoStream : CryptoStream {
1475                         public bool DisposeCalled { get; private set;}
1476
1477                         public MyCryptoStream(Stream stream, ICryptoTransform transform)
1478                                                 : base(stream, transform, CryptoStreamMode.Read)
1479                         {
1480                         }
1481
1482                         protected override void Dispose(bool disposing)
1483                         {
1484                                 base.Dispose(disposing);
1485                                 DisposeCalled = true;
1486                         }
1487                 }
1488
1489                 class ExpandTransform : ICryptoTransform {
1490
1491                         public bool CanReuseTransform {
1492                                 get { return true; }
1493                         }
1494
1495                         public bool CanTransformMultipleBlocks {
1496                                 get; private set;
1497                         }
1498
1499                         public int InputBlockSize {
1500                                 get { return 1; }
1501                         }
1502
1503                         public int OutputBlockSize {
1504                                 get; private set;
1505                         }
1506
1507                         public ExpandTransform (bool canTranformMultipleBlocks, int outputBlockSize)
1508                         {
1509                                 this.CanTransformMultipleBlocks = canTranformMultipleBlocks;
1510                                 this.OutputBlockSize = outputBlockSize;
1511                         }
1512
1513                         public void Dispose ()
1514                         {
1515                         }
1516
1517                         public int TransformBlock (byte [] inputBuffer, int inputOffset, int inputCount, byte [] outputBuffer, int outputOffset)
1518                         {
1519                                 var ret = 0;
1520                                 for (var i = 0; i < inputCount; i++, inputOffset++) {
1521                                         for (var j = 0; j < OutputBlockSize; j++, outputOffset++, ret++) {
1522                                                 outputBuffer [outputOffset] = inputBuffer [inputOffset];
1523                                         }
1524                                 }
1525                                 return ret;
1526                         }
1527
1528                         public byte [] TransformFinalBlock (byte [] inputBuffer, int inputOffset, int inputCount)
1529                         {
1530                                 var outputBuffer = new byte [inputCount * OutputBlockSize];
1531                                 TransformBlock (inputBuffer, inputOffset, inputCount, outputBuffer, 0);
1532                                 return outputBuffer;
1533                         }
1534                 }
1535
1536                 static string[] expand_values = {
1537                         "00-01-02-03-04-05-06-07",
1538                         "00-00-01-01-02-02-03-03-04-04-05-05-06-06-07-07",
1539                         "00-00-00-01-01-01-02-02-02-03-03-03-04-04-04-05-05-05-06-06-06-07-07-07",
1540                         "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",
1541                         "00-01-02-03-04-05-06-07",
1542                         "00-00-01-01-02-02-03-03-04-04-05-05-06-06-07-07",
1543                         "00-00-00-01-01-01-02-02-02-03-03-03-04-04-04-05-05-05-06-06-06-07-07-07",
1544                         "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"
1545                 };
1546
1547                 [Test]
1548                 public void Expand ()
1549                 {
1550                         int n = 0;
1551                         foreach (var transformMultiple in new [] { false, true }) {
1552                                 foreach (var outputBlockSize in new [] { 1, 2, 3, 4 }) {
1553                                         var expantedStream = new MemoryStream ();
1554                                         var inputData = new byte [] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
1555
1556                                         using (var stream = new CryptoStream (expantedStream, new ExpandTransform (transformMultiple, outputBlockSize), CryptoStreamMode.Write)) {
1557                                                 stream.Write (inputData, 0, inputData.Length);
1558                                         }
1559                                         expantedStream.Close ();
1560
1561                                         string value = BitConverter.ToString (expantedStream.ToArray ());
1562                                         Assert.AreEqual (expand_values [n++], value);
1563                                 }
1564                         }
1565                 }
1566
1567                 class CompressTransform : ICryptoTransform {
1568                         public bool CanReuseTransform {
1569                                 get { return true; }
1570                         }
1571
1572                         public bool CanTransformMultipleBlocks {
1573                                 get { return true; }
1574                         }
1575
1576                         public int InputBlockSize {
1577                                 get; private set;
1578                         }
1579
1580                         public int OutputBlockSize {
1581                                 get { return 1; }
1582                         }
1583
1584                         public CompressTransform (int inputBlockSize)
1585                         {
1586                                 this.InputBlockSize = inputBlockSize;
1587                         }
1588
1589                         public void Dispose ()
1590                         {
1591                         }
1592
1593                         private int bufferedCount = 0;
1594
1595                         public int TransformBlock (byte [] inputBuffer, int inputOffset, int inputCount, byte [] outputBuffer, int outputOffset)
1596                         {
1597                                 var ret = 0;
1598                                 for (var i = 0; i < inputCount; i++, inputOffset++) {
1599                                         if (++bufferedCount == InputBlockSize) {
1600                                                 outputBuffer [outputOffset++] = inputBuffer [inputOffset];
1601                                                 ret++;
1602                                                 bufferedCount = 0;
1603                                         }
1604                                 }
1605                                 return ret;
1606                         }
1607
1608                         public byte [] TransformFinalBlock (byte [] inputBuffer, int inputOffset, int inputCount)
1609                         {
1610                                 var outputBuffer = new byte [inputCount * OutputBlockSize];
1611                                 var ret = TransformBlock (inputBuffer, inputOffset, inputCount, outputBuffer, 0);
1612                                 byte[] result = new byte [ret];
1613                                 Array.Copy (outputBuffer, result, ret);
1614                                 return result;
1615                         }
1616                 }
1617
1618                 static string[] compress_values = {
1619                         "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",
1620                         "01-03-05-07-09-0B-0D-0F-11-13-15-17-19-1B-1D-1F",
1621                         "02-05-08-0B-0E-11-14-17-1A-1D",
1622                         "03-07-0B-0F-13-17-1B-1F",
1623                 };
1624
1625                 [Test]
1626                 public void Compress ()
1627                 {
1628                         int n = 0;
1629                         foreach (var inputBlockSize in new [] { 1, 2, 3, 4 }) {
1630                                 var inputData = new byte [] {
1631                                         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
1632                                         0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
1633                                         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
1634                                         0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
1635                                 };
1636
1637                                 using (var stream = new CryptoStream (new MemoryStream (inputData), new CompressTransform (inputBlockSize), CryptoStreamMode.Read)) {
1638                                         var buffer = new byte [inputData.Length];
1639                                         var ret = stream.Read (buffer, 0, buffer.Length);
1640                                         string value = BitConverter.ToString (buffer, 0, ret);
1641                                         Assert.AreEqual (compress_values [n++], value);
1642                                 }
1643                         }
1644                 }
1645
1646                 class MyCryptAlgorithm : ICryptoTransform {
1647                         public bool CanReuseTransform { get { return true; } }
1648                         public bool CanTransformMultipleBlocks { get { return false; } }
1649                         public int InputBlockSize { get { return 128 * 1024; } }
1650                         public int OutputBlockSize { get { return 64 * 1024; } }
1651
1652                         public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
1653                         {
1654                                 return this.OutputBlockSize;
1655                         }
1656
1657                         public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
1658                         {
1659                                 return new byte[this.OutputBlockSize];
1660                         }
1661
1662                         public void Dispose() {}
1663                 }
1664
1665                 class MyStream : Stream {
1666                         public bool FlushCounterEnabled;
1667                         public int FlushCounter;
1668
1669                         public override bool CanRead
1670                         {
1671                                 get {
1672                                         return true;
1673                                 }
1674                         }
1675
1676                         public override bool CanSeek
1677                         {
1678                                 get {
1679                                         return true;
1680                                 }
1681                         }
1682
1683                         public override bool CanWrite
1684                         {
1685                                 get {
1686                                         return true;
1687                                 }
1688                         }
1689
1690                         public override long Length
1691                         {
1692                                 get {
1693                                         return 0;
1694                                 }
1695                         }
1696
1697                         public override long Position
1698                         {
1699                                 get {
1700                                         return 0;
1701                                 }
1702                                 set {
1703                                 }
1704                         }
1705
1706                         public override void Flush ()
1707                         {
1708                                 if (FlushCounterEnabled)
1709                                         FlushCounter++;
1710                         }
1711
1712                         public override int Read (byte[] buffer, int offset, int count)
1713                         {
1714                                 return 0;
1715                         }
1716
1717                         public override int ReadByte ()
1718                         {
1719                                 return -1;
1720                         }
1721
1722                         public override long Seek (long offset, SeekOrigin origin)
1723                         {
1724                                 return 0;
1725                         }
1726
1727                         public override void SetLength (long value)
1728                         {
1729                         }
1730
1731                         public override void Write (byte[] buffer, int offset, int count)
1732                         {
1733                         }
1734
1735                         public override void WriteByte (byte value)
1736                         {
1737                         }
1738                 }
1739         }
1740 }