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