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