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