update readme (#21797)
[mono-project.git] / mcs / class / corlib / Test / System.Security.Cryptography / CryptoStreamTest.cs
blob7f3790421f6231ac5bab86dc652848c912fd4508
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.
30 /* WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING *
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.
35 * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING */
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;
45 namespace MonoTests.System.Security.Cryptography {
47 // much useful for debugging
48 public class DebugStream : MemoryStream {
50 // constructor
52 public DebugStream () : base () {}
53 public DebugStream (byte[] buffer) : base (buffer) {}
54 public DebugStream (int capacity) : base (capacity) {}
56 public override bool CanRead {
57 get { return base.CanRead; }
60 public override bool CanSeek {
61 get { return base.CanSeek; }
64 public override bool CanWrite {
65 get { return base.CanWrite; }
68 public override int Capacity {
69 get { return base.Capacity; }
70 set { base.Capacity = value; }
73 public override long Length {
74 get { return base.Length; }
77 public override long Position {
78 get { return base.Position; }
79 set { base.Position = value; }
82 // methods
84 public override void Close ()
86 base.Close ();
89 public override void Flush ()
91 base.Flush ();
94 public override byte[] GetBuffer ()
96 return base.GetBuffer ();
99 public override int Read ([In,Out] byte[] buffer, int offset, int count)
101 int len = base.Read (buffer, offset, count);
102 return len;
105 public override int ReadByte ()
107 return base.ReadByte ();
110 public override long Seek (long offset, SeekOrigin loc)
112 return base.Seek (offset, loc);
115 public override void SetLength (long value)
117 base.SetLength (value);
120 public override byte[] ToArray ()
122 return base.ToArray ();
125 public override void Write (byte[] buffer, int offset, int count)
127 base.Write (buffer, offset, count);
130 public override void WriteByte (byte value)
132 base.WriteByte (value);
135 public override void WriteTo (Stream stream)
137 base.WriteTo (stream);
141 [TestFixture]
142 public class CryptoStreamTest {
144 Stream readStream;
145 Stream writeStream;
146 ICryptoTransform encryptor;
147 CryptoStream cs;
148 SymmetricAlgorithm aes;
150 [SetUp]
151 public void SetUp ()
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 ();
161 public void AssertEquals (string msg, byte[] array1, byte[] array2)
163 Assert.AreEqual (array1, array2, msg);
166 [Test]
167 [ExpectedException (typeof (NullReferenceException))]
168 public void StreamNull ()
170 cs = new CryptoStream (null, encryptor, CryptoStreamMode.Read);
173 [Test]
174 [ExpectedException (typeof (NullReferenceException))]
175 public void TransformNull ()
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);
183 [Test]
184 public void StreamReadModeRead ()
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");
192 [Test]
193 [ExpectedException (typeof (ArgumentException))]
194 public void StreamReadModeWrite ()
196 cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Write);
199 [Test]
200 [ExpectedException (typeof (ArgumentException))]
201 public void StreamWriteModeRead ()
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);
214 [Test]
215 public void StreamWriteModeWrite ()
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");
223 [Test]
224 [ExpectedException (typeof (NotSupportedException))]
225 public void GetLength ()
227 DebugStream debug = new DebugStream ();
228 cs = new CryptoStream (debug, encryptor, CryptoStreamMode.Read);
229 long x = cs.Length;
232 [Test]
233 [ExpectedException (typeof (NotSupportedException))]
234 public void GetPosition ()
236 DebugStream debug = new DebugStream ();
237 cs = new CryptoStream (debug, encryptor, CryptoStreamMode.Read);
238 long x = cs.Position;
241 [Test]
242 [ExpectedException (typeof (NotSupportedException))]
243 public void SetPosition ()
245 DebugStream debug = new DebugStream ();
246 cs = new CryptoStream (debug, encryptor, CryptoStreamMode.Read);
247 cs.Position = 1;
250 [Test]
251 [ExpectedException (typeof (NotSupportedException))]
252 public void Seek ()
254 DebugStream debug = new DebugStream ();
255 cs = new CryptoStream (debug, encryptor, CryptoStreamMode.Read);
256 cs.Seek (0, SeekOrigin.Begin);
259 [Test]
260 [ExpectedException (typeof (NotSupportedException))]
261 public void SetLength ()
263 DebugStream debug = new DebugStream ();
264 cs = new CryptoStream (debug, encryptor, CryptoStreamMode.Read);
265 cs.SetLength (0);
268 [Test]
269 // LAMESPEC : [ExpectedException (typeof (NotSupportedException))]
270 public void FlushReadStream ()
272 cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
273 cs.Flush ();
276 [Test]
277 public void FlushFinalBlockReadStream ()
279 cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
280 cs.FlushFinalBlock ();
283 [Test]
284 [ExpectedException (typeof (NotSupportedException))]
285 public void FlushFinalBlock_Dual ()
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 ();
297 [Test]
298 // LAMESPEC or MS BUG [ExpectedException (typeof (ObjectDisposedException))]
299 [ExpectedException (typeof (NotSupportedException))]
300 public void FlushFinalBlock_Disposed ()
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 ();
310 [Test]
311 // LAMESPEC or MS BUG [ExpectedException (typeof (ObjectDisposedException))]
312 public void Read_Disposed ()
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) {
327 #if !MOBILE
328 [Test]
329 [ExpectedException (typeof (NotSupportedException))]
330 public void Read_Disposed_Break ()
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);
342 #endif
344 [Test]
345 [ExpectedException (typeof (NotSupportedException))]
346 public void Read_WriteStream ()
348 cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
349 byte[] buffer = new byte [8];
350 cs.Read (buffer, 0, 8);
353 [Test]
354 [ExpectedException (typeof (NullReferenceException))]
355 public void Read_NullBuffer ()
357 cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
358 cs.Read (null, 0, 8);
361 [Test]
362 public void Read_EmptyBuffer_ZeroCount ()
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");
370 [Test]
371 [ExpectedException (typeof (ArgumentOutOfRangeException))]
372 public void Read_NegativeOffset ()
374 byte[] buffer = new byte [8];
375 cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
376 cs.Read (buffer, -1, 8);
379 [Test]
380 public void Read_ZeroCount ()
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");
388 [Test]
389 [ExpectedException (typeof (ArgumentOutOfRangeException))]
390 public void Read_NegativeCount ()
392 byte[] buffer = new byte [8];
393 cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
394 cs.Read (buffer, 0, -1);
397 [Test]
398 [ExpectedException (typeof (ArgumentException))]
399 public void Read_OverflowCount ()
401 byte[] buffer = new byte [8];
402 cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
403 cs.Read (buffer, 0, Int32.MaxValue);
406 [Test]
407 [ExpectedException (typeof (ArgumentException))]
408 public void Read_InvalidOffset ()
410 byte[] buffer = new byte [8];
411 cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
412 cs.Read (buffer, 5, 4);
415 [Test]
416 [ExpectedException (typeof (ArgumentException))]
417 public void Read_OverflowOffset ()
419 byte[] buffer = new byte [8];
420 cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
421 cs.Read (buffer, Int32.MaxValue, 4);
424 [Test]
425 [ExpectedException (typeof (NotSupportedException))]
426 public void Write_Disposed ()
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);
437 [Test]
438 [ExpectedException (typeof (NotSupportedException))]
439 public void Write_ReadStream ()
441 cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read);
442 byte[] buffer = new byte [8];
443 cs.Write (buffer, 0, 8);
446 [Test]
447 [ExpectedException (typeof (NullReferenceException))]
448 public void Write_NullBuffer ()
450 cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
451 cs.Write (null, 0, 8);
454 [Test]
455 public void Write_EmptyBuffer_ZeroCount ()
457 byte[] buffer = new byte [0];
458 cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
459 cs.Write (buffer, 0, 0);
462 [Test]
463 [ExpectedException (typeof (ArgumentOutOfRangeException))]
464 public void Write_NegativeOffset ()
466 byte[] buffer = new byte [8];
467 cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
468 cs.Write (buffer, -1, 8);
471 [Test]
472 [ExpectedException (typeof (ArgumentException))]
473 public void Write_OverflowOffset ()
475 byte[] buffer = new byte [8];
476 cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
477 cs.Write (buffer, Int32.MaxValue, 8);
480 [Test]
481 public void Write_ZeroCount ()
483 byte[] buffer = new byte [8];
484 cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
485 cs.Write (buffer, 0, 0);
488 [Test]
489 [ExpectedException (typeof (ArgumentOutOfRangeException))]
490 public void Write_NegativeCount ()
492 byte[] buffer = new byte [8];
493 cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write);
494 cs.Write (buffer, 0, -1);
497 [Test]
498 [ExpectedException (typeof (ArgumentException))]
499 public void Write_InvalidOffset ()
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);
507 [Test]
508 [ExpectedException (typeof (ArgumentException))]
509 public void Write_OverflowCount ()
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);
517 [Test]
518 public void FullRoundtripRead ()
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 ();
527 encrypted = mem1.ToArray ();
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");
540 // bugzilla 46143 (adapted from test case by Joerg Rosenkranz)
541 [Test]
542 public void PartialRoundtripRead ()
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 ();
551 encrypted = mem1.ToArray ();
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");
565 // bugzilla: 40689 (adapted from test case by Henning Westerholt)
566 [Test]
567 public void WriteOnBlockWithFinal ()
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 ();
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
581 MemoryStream msout = new MemoryStream ();
582 msout.SetLength (0);
584 byte[] tmp = new byte [1024];
585 long readlen = 0;
586 long totallen = msin.Length;
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);
595 Assert.AreEqual (2200, msout.Length, "Decryped Write Length");
597 dec.Close ();
598 dec.Clear ();
599 msout.Close ();
600 msin.Close ();
602 Assert.AreEqual (2208, readlen, "Read Length"); // 2200 + padding
605 [Test]
606 public void PreGeneratedStreams ()
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 ();
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 ();
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;
653 private byte[] EmptyStream (PaddingMode mode)
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 ();
667 [Test]
668 public void EmptyStreamWithPaddingNone ()
670 byte[] result = EmptyStream (PaddingMode.None);
671 Assert.AreEqual (0, result.Length, "Result Length");
674 [Test]
675 public void EmptyStreamWithPaddingPKCS7 ()
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");
683 [Test]
684 public void EmptyStreamWithPaddingZeros ()
686 byte[] result = EmptyStream (PaddingMode.Zeros);
687 Assert.AreEqual (0, result.Length, "Result Length");
690 // bugzilla: 49323 (adapted from test case by Carlos Guzmán Álvarez)
691 [Test]
692 public void MultiblocksWithPartial ()
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};
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};
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");
717 // Adapted from Subba Rao Thirumoorthy email on mono-devel-list (december 2003)
718 private byte[] NonMultipleOfBlockSize_Encrypt (ICryptoTransform ct, byte[] data)
720 DebugStream stream = new DebugStream ();
721 CryptoStream CryptStream = new CryptoStream (stream, ct, CryptoStreamMode.Write);
723 int len = 0;
724 long myLength = 0;
725 byte[] Buffer = new byte [1024];
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;
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");
743 CryptStream.Close();
744 stream.Close();
745 return result;
748 private byte[] NonMultipleOfBlockSize_Decrypt (ICryptoTransform ct, byte[] data)
750 DebugStream stream = new DebugStream (data);
751 CryptoStream CryptStream = new CryptoStream (stream, ct, CryptoStreamMode.Read);
753 int len = 0;
754 long myLength = 0;
755 byte[] Buffer = new Byte [1024];
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;
766 byte[] result = fout.ToArray ();
767 CryptStream.Close ();
768 stream.Close ();
769 return result;
772 [Test]
773 public void NonMultipleOfBlockSize ()
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];
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");
784 ICryptoTransform decryptor = aes.CreateDecryptor (key, iv);
785 byte[] decdata = NonMultipleOfBlockSize_Decrypt (decryptor, encdata);
786 Assert.AreEqual (data.Length, decdata.Length, "Decrypted Data Length");
788 int i = 0;
789 bool b = true;
790 while (b && (i < data.Length)) {
791 b = (data [i] == decdata [i]);
792 i++;
794 Assert.IsTrue (b, "NonMultipleOfBlockSize");
797 // bugzilla: 51322 - indirectly related but it explains why my first (unapplied) patch didn't work
798 [Test]
799 public void DecryptPartial_TransformFinalBlock_required ()
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 ();
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 ();
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");
820 [Test]
821 public void DecryptPartial_TransformFinalBlock_2Pass ()
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 ();
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 ();
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 ();
845 // based on http://www.c-sharpcorner.com/Code/2002/May/FileEncryption.asp
846 [Test]
847 public void WriteByteReadByte ()
849 DebugStream original = new DebugStream (Encoding.Unicode.GetBytes ("ximian"));
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);
857 int data;
858 while ((data = original.ReadByte ()) != -1)
859 cs.WriteByte((byte) data);
860 cs.Close ();
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");
865 encrypted = new DebugStream (result);
866 DebugStream decrypted = new DebugStream ();
867 cs = new CryptoStream (encrypted, des.CreateDecryptor (key, iv), CryptoStreamMode.Read);
869 while ((data = cs.ReadByte ()) != -1)
870 decrypted.WriteByte((byte) data);
871 cs.Close ();
872 decrypted.Close ();
874 Assert.AreEqual ("ximian", Encoding.Unicode.GetString (decrypted.ToArray ()), "W/R Byte Roundtrip");
877 // based http://www.4guysfromrolla.com/webtech/090501-1.shtml
879 public string EncryptData (ICryptoTransform des, string strData)
881 strData = String.Format("{0,5:00000}" + strData, strData.Length);
882 byte[] data = Encoding.ASCII.GetBytes (strData);
884 MemoryStream mStream = new MemoryStream (data);
885 CryptoStream cs = new CryptoStream (mStream, des, CryptoStreamMode.Read);
886 MemoryStream mOut = new MemoryStream ();
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);
895 while (bytesRead > 0);
897 return Convert.ToBase64String (mOut.ToArray ());
900 public string DecryptData (ICryptoTransform des, string strData)
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);
910 [Test]
911 public void EncryptOnRead ()
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);
920 DES des = DES.Create ();
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
1141 // based on System.Security assembly XmlDsigBase64TransformTest
1143 [Test]
1144 public void FromBase64_Write ()
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);
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 ();
1158 string result = Encoding.UTF8.GetString (encoded);
1159 Assert.AreEqual (expected, result, "FromBase64_Write");
1162 [Test]
1163 public void FromBase64_Read ()
1165 byte[] original = Encoding.UTF8.GetBytes ("aHR0cDovL3d3dy5nby1tb25vLmNvbS8=");
1166 DebugStream debug = new DebugStream (original);
1168 ICryptoTransform base64 = new FromBase64Transform ();
1169 cs = new CryptoStream (debug, base64, CryptoStreamMode.Read);
1171 byte[] data = new byte [1024];
1172 int length = cs.Read (data, 0, data.Length);
1173 cs.Close ();
1175 string result = Encoding.UTF8.GetString (data, 0, length);
1176 Assert.AreEqual ("http://www.go-mono.com/", result, "ToBase64_Read");
1179 [Test]
1180 public void ToBase64_Write ()
1182 byte[] data = Encoding.UTF8.GetBytes ("http://www.go-mono.com/");
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 ();
1191 string result = Encoding.UTF8.GetString (encoded);
1192 Assert.AreEqual ("aHR0cDovL3d3dy5nby1tb25vLmNvbS8=", result, "ToBase64_Write");
1195 [Test]
1196 public void ToBase64_Read ()
1198 byte[] original = Encoding.UTF8.GetBytes ("http://www.go-mono.com/");
1199 DebugStream debug = new DebugStream (original);
1201 ICryptoTransform base64 = new ToBase64Transform ();
1202 cs = new CryptoStream (debug, base64, CryptoStreamMode.Read);
1204 byte[] data = new byte [1024];
1205 int length = cs.Read (data, 0, data.Length);
1206 cs.Close ();
1208 string result = Encoding.UTF8.GetString (data, 0, length);
1209 Assert.AreEqual ("aHR0cDovL3d3dy5nby1tb25vLmNvbS8=", result, "ToBase64_Read");
1212 // Cascaded CryptoStream - like sample in book .NET Framework Security, chapter 30
1214 [Test]
1215 public void CascadedCryptoStream_Write ()
1217 DebugStream debug = new DebugStream ();
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);
1225 MD5 hash = MD5.Create ();
1226 CryptoStream csh = new CryptoStream (cse, hash, CryptoStreamMode.Write);
1228 byte[] data = Encoding.UTF8.GetBytes ("http://www.go-mono.com/");
1229 csh.Write (data, 0, data.Length);
1230 csh.FlushFinalBlock ();
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");
1237 [Test]
1238 public void CascadedCryptoStream_Read ()
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);
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);
1249 MD5 hash = MD5.Create ();
1250 CryptoStream csh = new CryptoStream (csd, hash, CryptoStreamMode.Read);
1252 byte[] data = new byte [1024];
1253 int length = csh.Read (data, 0, data.Length);
1254 csh.Close ();
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");
1262 // bugzilla: 60573 - the number of block is not reduced for encryptors
1264 [Test]
1265 public void EncryptorWriteBlocks ()
1267 DebugStream debug = new DebugStream ();
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);
1274 byte[] data = new byte [64];
1275 cse.Write (data, 0, 64);
1276 Assert.AreEqual (64, debug.Length, "Length");
1277 cse.Close ();
1280 [Test]
1281 public void DecryptorWriteBlocks ()
1283 DebugStream debug = new DebugStream ();
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);
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
1296 [Test]
1297 public void PaddingModeNone ()
1299 byte[] Key = new byte [16];
1300 byte[] IV = new byte [16];
1301 byte[] Buffer = new byte [64];
1303 Rijndael alg = Rijndael.Create ();
1304 alg.Mode = CipherMode.CBC;
1305 alg.Padding = PaddingMode.None;
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 ();
1313 Assert.AreEqual (64, cms.ToArray ().Length, "Length");
1316 private void WriteByte (PaddingMode mode, bool padded)
1318 byte[] Key = new byte[16];
1319 byte[] IV = new byte[16];
1320 byte[] Buffer = new byte[64];
1322 Rijndael alg = Rijndael.Create ();
1323 alg.Mode = CipherMode.CBC;
1324 alg.Padding = mode;
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 ();
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");
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 ();
1345 byte[] plaintext = cms.ToArray ();
1346 Assert.AreEqual (64, plaintext.Length, mode.ToString () + ".Decrypted.Length");
1348 Assert.AreEqual (Buffer, plaintext, mode.ToString () + ".Date");
1351 [Test]
1352 public void WriteByte ()
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);
1361 [Test]
1362 public void ReadModeDispose_FinalBlock ()
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))
1369 byte b = sha1.Hash [0]; // This will throw if TransformFinalBlock not called in sha1
1370 GC.KeepAlive (b); // just the warning...
1374 [Test]
1375 public void CustomDisposeCalled ()
1377 using (MemoryStream mem = new MemoryStream(new byte[] { 1, 2, 3 }, false)) {
1378 MyCryptoStream cs;
1379 using (cs = new MyCryptoStream (mem, SHA1.Create()))
1382 Assert.IsTrue (cs.DisposeCalled, "#1");
1386 [Test]
1387 public void ExplicitFlush ()
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;
1396 Assert.IsTrue (ms.FlushCounter == 0);
1399 [Test]
1400 public void ImplicitFlush ()
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)) {
1407 Assert.IsTrue (ms.FlushCounter == 1);
1410 [Test]
1411 public void ImplicitFlushCascade ()
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)) {
1419 Assert.IsTrue (ms.FlushCounter == 1);
1422 [Test]
1423 [ExpectedException (typeof (ArgumentException))]
1424 public void Ctor_InvalidEnumValue ()
1426 CryptoStream cs = new CryptoStream (Stream.Null, SHA1.Create (), (CryptoStreamMode) 0xff);
1429 [Test]
1430 public void OutputBlock_Smaller ()
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);
1439 class MyCryptoStream : CryptoStream {
1440 public bool DisposeCalled { get; private set;}
1442 public MyCryptoStream(Stream stream, ICryptoTransform transform)
1443 : base(stream, transform, CryptoStreamMode.Read)
1447 protected override void Dispose(bool disposing)
1449 base.Dispose(disposing);
1450 DisposeCalled = true;
1454 class ExpandTransform : ICryptoTransform {
1456 public bool CanReuseTransform {
1457 get { return true; }
1460 public bool CanTransformMultipleBlocks {
1461 get; private set;
1464 public int InputBlockSize {
1465 get { return 1; }
1468 public int OutputBlockSize {
1469 get; private set;
1472 public ExpandTransform (bool canTranformMultipleBlocks, int outputBlockSize)
1474 this.CanTransformMultipleBlocks = canTranformMultipleBlocks;
1475 this.OutputBlockSize = outputBlockSize;
1478 public void Dispose ()
1482 public int TransformBlock (byte [] inputBuffer, int inputOffset, int inputCount, byte [] outputBuffer, int outputOffset)
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];
1490 return ret;
1493 public byte [] TransformFinalBlock (byte [] inputBuffer, int inputOffset, int inputCount)
1495 var outputBuffer = new byte [inputCount * OutputBlockSize];
1496 TransformBlock (inputBuffer, inputOffset, inputCount, outputBuffer, 0);
1497 return outputBuffer;
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"
1512 [Test]
1513 public void Expand ()
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 };
1521 using (var stream = new CryptoStream (expantedStream, new ExpandTransform (transformMultiple, outputBlockSize), CryptoStreamMode.Write)) {
1522 stream.Write (inputData, 0, inputData.Length);
1524 expantedStream.Close ();
1526 string value = BitConverter.ToString (expantedStream.ToArray ());
1527 Assert.AreEqual (expand_values [n++], value);
1532 class CompressTransform : ICryptoTransform {
1533 public bool CanReuseTransform {
1534 get { return true; }
1537 public bool CanTransformMultipleBlocks {
1538 get { return true; }
1541 public int InputBlockSize {
1542 get; private set;
1545 public int OutputBlockSize {
1546 get { return 1; }
1549 public CompressTransform (int inputBlockSize)
1551 this.InputBlockSize = inputBlockSize;
1554 public void Dispose ()
1558 private int bufferedCount = 0;
1560 public int TransformBlock (byte [] inputBuffer, int inputOffset, int inputCount, byte [] outputBuffer, int outputOffset)
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;
1570 return ret;
1573 public byte [] TransformFinalBlock (byte [] inputBuffer, int inputOffset, int inputCount)
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;
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",
1590 [Test]
1591 public void Compress ()
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,
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);
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; } }
1617 public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
1619 return this.OutputBlockSize;
1622 public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
1624 return new byte[this.OutputBlockSize];
1627 public void Dispose() {}
1630 class MyStream : Stream {
1631 public bool FlushCounterEnabled;
1632 public int FlushCounter;
1634 public override bool CanRead
1636 get {
1637 return true;
1641 public override bool CanSeek
1643 get {
1644 return true;
1648 public override bool CanWrite
1650 get {
1651 return true;
1655 public override long Length
1657 get {
1658 return 0;
1662 public override long Position
1664 get {
1665 return 0;
1667 set {
1671 public override void Flush ()
1673 if (FlushCounterEnabled)
1674 FlushCounter++;
1677 public override int Read (byte[] buffer, int offset, int count)
1679 return 0;
1682 public override int ReadByte ()
1684 return -1;
1687 public override long Seek (long offset, SeekOrigin origin)
1689 return 0;
1692 public override void SetLength (long value)
1696 public override void Write (byte[] buffer, int offset, int count)
1700 public override void WriteByte (byte value)