// // CryptoStreamTest.cs - NUnit Test Cases for CryptoStream // // Author: // Sebastien Pouliot // // (C) 2003 Motus Technologies Inc. (http://www.motus.com) // (C) 2004 Novell (http://www.novell.com) // /* WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * * * DO NOT USE ANY OF THE TEST CASE AS SAMPLES FOR YOUR OWN CODE. MANY * CASES CONTAINS ERRORS AND AREN'T SECURE IN THEIR USE. * * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING * WARNING */ using NUnit.Framework; using System; using System.IO; using System.Reflection; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; namespace MonoTests.System.Security.Cryptography { // much useful for debugging public class DebugStream : MemoryStream { // constructor public DebugStream () : base () {} public DebugStream (byte[] buffer) : base (buffer) {} public DebugStream (int capacity) : base (capacity) {} public override bool CanRead { get { return base.CanRead; } } public override bool CanSeek { get { return base.CanSeek; } } public override bool CanWrite { get { return base.CanWrite; } } public override int Capacity { get { return base.Capacity; } set { base.Capacity = value; } } public override long Length { get { return base.Length; } } public override long Position { get { return base.Position; } set { base.Position = value; } } // methods public override void Close () { base.Close (); } public override void Flush () { base.Flush (); } public override byte[] GetBuffer () { return base.GetBuffer (); } public override int Read ([In,Out] byte[] buffer, int offset, int count) { int len = base.Read (buffer, offset, count); return len; } public override int ReadByte () { return base.ReadByte (); } public override long Seek (long offset, SeekOrigin loc) { return base.Seek (offset, loc); } public override void SetLength (long value) { base.SetLength (value); } public override byte[] ToArray () { return base.ToArray (); } public override void Write (byte[] buffer, int offset, int count) { base.Write (buffer, offset, count); } public override void WriteByte (byte value) { base.WriteByte (value); } public override void WriteTo (Stream stream) { base.WriteTo (stream); } } [TestFixture] public class CryptoStreamTest : Assertion { Stream readStream; Stream writeStream; ICryptoTransform encryptor; ICryptoTransform decryptor; CryptoStream cs; SymmetricAlgorithm aes; [SetUp] void SetUp () { if (readStream == null) { readStream = new FileStream ("read", FileMode.OpenOrCreate, FileAccess.Read); writeStream = new FileStream ("write", FileMode.OpenOrCreate, FileAccess.Write); aes = SymmetricAlgorithm.Create (); encryptor = aes.CreateEncryptor (); decryptor = aes.CreateEncryptor (); } } [TearDown] void CleanUp () { try { if (File.Exists ("read")) File.Delete ("read"); if (File.Exists ("write")) File.Delete ("write"); } catch {} } public void AssertEquals (string msg, byte[] array1, byte[] array2) { AllTests.AssertEquals (msg, array1, array2); } [Test] [ExpectedException (typeof (NullReferenceException))] public void StreamNull () { cs = new CryptoStream (null, encryptor, CryptoStreamMode.Read); } [Test] [ExpectedException (typeof (NullReferenceException))] public void TransformNull () { MemoryStream write = new MemoryStream (8); byte[] data = {0, 1, 2, 3, 4, 5, 6, 7}; cs = new CryptoStream (write, null, CryptoStreamMode.Write); cs.Write (data, 0, 8); } [Test] public void StreamReadModeRead () { cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read); Assert ("Read.CanRead", cs.CanRead); Assert ("Read.CanWrite", !cs.CanWrite); Assert ("Read.CanSeek", !cs.CanSeek); } [Test] [ExpectedException (typeof (ArgumentException))] public void StreamReadModeWrite () { cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Write); } [Test] [ExpectedException (typeof (ArgumentException))] public void StreamWriteModeRead () { cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Read); } [Test] public void StreamWriteModeWrite () { cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write); Assert ("Read.CanRead", !cs.CanRead); Assert ("Read.CanWrite", cs.CanWrite); Assert ("Read.CanSeek", !cs.CanSeek); } [Test] [ExpectedException (typeof (NotSupportedException))] public void GetLength () { cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read); long x = cs.Length; } [Test] [ExpectedException (typeof (NotSupportedException))] public void GetPosition () { cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read); long x = cs.Position; } [Test] [ExpectedException (typeof (NotSupportedException))] public void SetPosition () { cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read); cs.Position = 1; } [Test] [ExpectedException (typeof (NotSupportedException))] public void Seek () { cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read); cs.Seek (0, SeekOrigin.Begin); } [Test] [ExpectedException (typeof (NotSupportedException))] public void SetLength () { cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read); cs.SetLength (0); } [Test] // LAMESPEC : [ExpectedException (typeof (NotSupportedException))] public void FlushReadStream () { cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read); cs.Flush (); } [Test] [ExpectedException (typeof (NotSupportedException))] public void FlushFinalBlockReadStream () { cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read); cs.FlushFinalBlock (); } [Test] [ExpectedException (typeof (NotSupportedException))] public void FlushFinalBlock_Dual () { byte[] data = {0, 1, 2, 3, 4, 5, 6, 7}; cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write); cs.Write (data, 0, data.Length); cs.FlushFinalBlock (); cs.FlushFinalBlock (); } [Test] // LAMESPEC or MS BUG [ExpectedException (typeof (ObjectDisposedException))] [ExpectedException (typeof (ArgumentNullException))] public void FlushFinalBlock_Disposed () { cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write); cs.Clear (); cs.FlushFinalBlock (); } [Test] // LAMESPEC or MS BUG [ExpectedException (typeof (ObjectDisposedException))] [ExpectedException (typeof (ArgumentNullException))] public void Read_Disposed () { byte[] buffer = new byte [8]; cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read); cs.Clear (); cs.Read (buffer, 0, 8); } [Test] // MS BUG [ExpectedException (typeof (ObjectDisposedException))] [Ignore ("Test cause System.ExecutionEngineException on MS runtime")] public void Read_Disposed_Break () { byte[] buffer = new byte [8]; cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read); int len = cs.Read (buffer, 0, 4); AssertEquals ("Read 4", 4, len); cs.Clear (); len = cs.Read (buffer, 3, 4); } [Test] [ExpectedException (typeof (NotSupportedException))] public void Read_WriteStream () { cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write); byte[] buffer = new byte [8]; cs.Read (buffer, 0, 8); } [Test] // [ExpectedException (typeof (ArgumentNullException))] [ExpectedException (typeof (NullReferenceException))] public void Read_NullBuffer () { cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read); cs.Read (null, 0, 8); } [Test] public void Read_EmptyBuffer_ZeroCount () { byte[] buffer = new byte [0]; cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read); int len = cs.Read (buffer, 0, 0); AssertEquals ("Read 0", 0, len); } [Test] [ExpectedException (typeof (ArgumentOutOfRangeException))] public void Read_NegativeOffset () { byte[] buffer = new byte [8]; cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read); cs.Read (buffer, -1, 8); } [Test] public void Read_ZeroCount () { byte[] buffer = new byte [8]; cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read); int len = cs.Read (buffer, 0, 0); AssertEquals ("Read 0", 0, len); } [Test] [ExpectedException (typeof (ArgumentOutOfRangeException))] public void Read_NegativeCount () { byte[] buffer = new byte [8]; cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read); cs.Read (buffer, 0, -1); } [Test] [ExpectedException (typeof (ArgumentException))] public void Read_InvalidOffset () { byte[] buffer = new byte [8]; cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read); cs.Read (buffer, 5, 4); } [Test] // MS BUG [ExpectedException (typeof (ObjectDisposedException))] [Ignore ("Test cause System.ExecutionEngineException on MS runtime")] public void Write_Disposed () { byte[] buffer = new byte [8]; cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write); cs.Clear (); cs.Write (buffer, 0, 8); } [Test] [ExpectedException (typeof (NotSupportedException))] public void Write_ReadStream () { cs = new CryptoStream (readStream, encryptor, CryptoStreamMode.Read); byte[] buffer = new byte [8]; cs.Write (buffer, 0, 8); } [Test] // [ExpectedException (typeof (ArgumentNullException))] [ExpectedException (typeof (NullReferenceException))] public void Write_NullBuffer () { cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write); cs.Write (null, 0, 8); } [Test] public void Write_EmptyBuffer_ZeroCount () { byte[] buffer = new byte [0]; cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write); cs.Write (buffer, 0, 0); } [Test] [ExpectedException (typeof (ArgumentOutOfRangeException))] public void Write_NegativeOffset () { byte[] buffer = new byte [8]; cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write); cs.Write (buffer, -1, 8); } [Test] public void Write_ZeroCount () { byte[] buffer = new byte [8]; cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write); cs.Write (buffer, 0, 0); } [Test] [ExpectedException (typeof (ArgumentOutOfRangeException))] public void Write_NegativeCount () { byte[] buffer = new byte [8]; cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write); cs.Write (buffer, 0, -1); } [Test] [ExpectedException (typeof (ArgumentException))] public void Write_InvalidOffset () { byte[] buffer = new byte [8]; cs = new CryptoStream (writeStream, encryptor, CryptoStreamMode.Write); cs.Write (buffer, 5, 4); } [Test] public void FullRoundtripRead () { byte[] encrypted; using (DebugStream mem1 = new DebugStream ()) { byte[] toEncrypt = Encoding.Unicode.GetBytes ("Please encode me!"); using (CryptoStream crypt = new CryptoStream (mem1, aes.CreateEncryptor (), CryptoStreamMode.Write)) { crypt.Write (toEncrypt, 0, toEncrypt.Length); crypt.FlushFinalBlock (); } encrypted = mem1.ToArray (); } using (DebugStream mem2 = new DebugStream (encrypted)) { byte[] buffer = new byte [1024]; CryptoStream cr = new CryptoStream (mem2, aes.CreateDecryptor (), CryptoStreamMode.Read); int len = cr.Read (buffer, 0, buffer.Length); cr.Close (); AssertEquals ("Full Length Read", 34, len); AssertEquals ("Full Block Read", "Please encode me!", Encoding.Unicode.GetString (buffer, 0, len)); } } // bugzilla 46143 (adapted from test case by Joerg Rosenkranz) [Test] public void PartialRoundtripRead () { byte[] encrypted; using (DebugStream mem1 = new DebugStream ()) { byte[] toEncrypt = Encoding.Unicode.GetBytes ("Please encode me!"); using (CryptoStream crypt = new CryptoStream (mem1, aes.CreateEncryptor (), CryptoStreamMode.Write)) { crypt.Write (toEncrypt, 0, toEncrypt.Length); crypt.FlushFinalBlock (); } encrypted = mem1.ToArray (); } using (DebugStream mem2 = new DebugStream (encrypted)) { byte[] buffer = new byte [1024]; CryptoStream cr = new CryptoStream (mem2, aes.CreateDecryptor (), CryptoStreamMode.Read); int len = cr.Read (buffer, 0, 20); cr.Clear (); cr.Close (); AssertEquals ("Partial Length Read", 20, len); AssertEquals ("Partial Block Read", "Please enc", Encoding.Unicode.GetString (buffer, 0, len)); } } // bugzilla: 40689 (adapted from test case by Henning Westerholt) [Test] public void WriteOnBlockWithFinal () { byte[] desKey = {0, 1, 2, 3, 4, 5, 6, 7}; byte[] desIV = {0, 1, 2, 3, 4, 5, 6, 7}; DES des = DES.Create (); MemoryStream msin = new MemoryStream (); CryptoStream enc = new CryptoStream (msin, des.CreateEncryptor (desKey, desIV), CryptoStreamMode.Write); byte[] data = new byte [2200]; enc.Write (data, 0, 2200); enc.FlushFinalBlock (); msin.Position = 0; AssertEquals ("Encryped Write Length", 2208, msin.Length); // 2200 + padding MemoryStream msout = new MemoryStream (); msout.SetLength (0); byte[] tmp = new byte [1024]; long readlen = 0; long totallen = msin.Length; CryptoStream dec = new CryptoStream (msout, des.CreateDecryptor (desKey, desIV), CryptoStreamMode.Write); int len = msin.Read (tmp, 0, 1024); while (len > 0) { dec.Write (tmp, 0, len); readlen += len; len = msin.Read (tmp, 0, 1024); } AssertEquals ("Decryped Write Length", 2200, msout.Length); dec.Close (); dec.Clear (); msout.Close (); msin.Close (); AssertEquals ("Read Length", 2208, readlen); // 2200 + padding } [Test] public void PreGeneratedStreams () { byte[] desKey = {0, 1, 2, 3, 4, 5, 6, 7}; byte[] desIV = {0, 1, 2, 3, 4, 5, 6, 7}; DES des = DES.Create (); for (int i=0; i < 9; i++) { MemoryStream msin = new MemoryStream (); CryptoStream enc = new CryptoStream (msin, des.CreateEncryptor (desKey, desIV), CryptoStreamMode.Write); byte[] data = new byte [i]; enc.Write (data, 0, i); enc.FlushFinalBlock (); string msg = "PreGeneratedStream #" + i; string result = BitConverter.ToString (msin.ToArray ()); switch (i) { case 0: AssertEquals (msg, "92-C9-DB-45-30-0B-93-2F", result); break; case 1: AssertEquals (msg, "08-CF-A1-37-BD-56-D0-65", result); break; case 2: AssertEquals (msg, "58-87-D4-9B-2C-27-97-0C", result); break; case 3: AssertEquals (msg, "07-35-90-94-68-7D-51-FB", result); break; case 4: AssertEquals (msg, "BF-00-98-C5-20-71-D0-DB", result); break; case 5: AssertEquals (msg, "1A-55-C8-6E-C1-9B-31-82", result); break; case 6: AssertEquals (msg, "2D-2B-76-41-61-0E-00-0C", result); break; case 7: AssertEquals (msg, "DC-FF-73-D2-7F-D7-48-5D", result); break; case 8: AssertEquals (msg, "E1-B2-46-E5-A7-C7-4C-BC-0E-40-4A-FC-08-92-B1-EB", result); break; } } } private byte[] EmptyStream (PaddingMode mode) { SymmetricAlgorithm algo = Rijndael.Create (); algo.Key = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; algo.IV = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; algo.Padding = mode; MemoryStream ms = new MemoryStream (); CryptoStream cs = new CryptoStream (ms, algo.CreateEncryptor(), CryptoStreamMode.Write); cs.Write (ms.GetBuffer (), 0, (int) ms.Length); cs.FlushFinalBlock (); cs.Flush (); return ms.ToArray (); } [Test] public void EmptyStreamWithPaddingNone () { byte[] result = EmptyStream (PaddingMode.None); AssertEquals ("Result Length", 0, result.Length); } [Test] public void EmptyStreamWithPaddingPKCS7 () { byte[] expected = { 0x07, 0xFE, 0xEF, 0x74, 0xE1, 0xD5, 0x03, 0x6E, 0x90, 0x0E, 0xEE, 0x11, 0x8E, 0x94, 0x92, 0x93 }; byte[] result = EmptyStream (PaddingMode.PKCS7); AssertEquals ("Result Length", 16, result.Length); AssertEquals ("Result", expected, result); } [Test] public void EmptyStreamWithPaddingZeros () { byte[] result = EmptyStream (PaddingMode.Zeros); AssertEquals ("Result Length", 0, result.Length); } // bugzilla: 49323 (adapted from test case by Carlos Guzmán Álvarez) [Test] public void MultiblocksWithPartial () { SymmetricAlgorithm tdes = new TripleDESCryptoServiceProvider (); 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}; tdes.IV = new byte[] {193, 227, 54, 132, 68, 172, 55, 91}; byte[] fragment = new byte[] {20, 0, 0, 12, 181, 134, 8, 230, 185, 75, 19, 129, 101, 142, 118, 190}; byte[] mac = new byte[] {42, 148, 229, 58, 185, 249, 154, 131, 157, 79, 176, 168, 143, 71, 0, 118, 5, 10, 95, 8}; // Encryption ( fragment + mac [+ padding + padding_length] ) MemoryStream ms = new MemoryStream (); CryptoStream cs = new CryptoStream (ms, tdes.CreateEncryptor (), CryptoStreamMode.Write); cs.Write (fragment, 0, fragment.Length); cs.Write (mac, 0, mac.Length); // Calculate padding_length int fragmentLength = fragment.Length + mac.Length + 1; int padding = (((fragmentLength / 8) * 8) + 8) - fragmentLength; // Write padding length byte cs.WriteByte ((byte)padding); cs.Close (); byte[] encrypted = ms.ToArray (); 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 }; AssertEquals ("MultiblocksWithPartial", expected, encrypted); } // Adapted from Subba Rao Thirumoorthy email on mono-devel-list (december 2003) private byte[] NonMultipleOfBlockSize_Encrypt (ICryptoTransform ct, byte[] data) { DebugStream stream = new DebugStream (); CryptoStream CryptStream = new CryptoStream (stream, ct, CryptoStreamMode.Write); int len = 0; long myLength = 0; byte[] Buffer = new byte [1024]; DebugStream fout = new DebugStream (data); while (myLength < data.Length) { len = fout.Read (Buffer, 0, 1023); if (len == 0) break; CryptStream.Write (Buffer, 0, len); CryptStream.Flush (); myLength = myLength + len; } CryptStream.FlushFinalBlock (); // we must ensure that the result is correct AssertEquals ("Length(final)", 64, len); byte[] result = stream.ToArray (); string end = BitConverter.ToString (result, 65520, 16); AssertEquals ("End part", "04-70-19-1D-28-C5-BD-9A-23-C6-60-E2-28-96-38-65", end); CryptStream.Close(); stream.Close(); return result; } private byte[] NonMultipleOfBlockSize_Decrypt (ICryptoTransform ct, byte[] data) { DebugStream stream = new DebugStream (data); CryptoStream CryptStream = new CryptoStream (stream, ct, CryptoStreamMode.Read); int len = 0; long myLength = 0; byte[] Buffer = new Byte [1024]; DebugStream fout = new DebugStream (); // each returned block must be 1023 bytes long // even if this isn't a multiple of the block size while ((len = CryptStream.Read (Buffer, 0, 1023)) != 0) { fout.Write (Buffer, 0, len); fout.Flush (); myLength = myLength + len; } byte[] result = fout.ToArray (); CryptStream.Close (); stream.Close (); return result; } [Test] public void NonMultipleOfBlockSize () { byte[] key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 }; byte[] iv = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 }; byte[] data = new byte [65536]; RijndaelManaged aes = new RijndaelManaged (); ICryptoTransform encryptor = aes.CreateEncryptor (key, iv); byte[] encdata = NonMultipleOfBlockSize_Encrypt (encryptor, data); AssertEquals ("Encrypted Data Length", (data.Length + (aes.BlockSize >> 3)), encdata.Length); ICryptoTransform decryptor = aes.CreateDecryptor (key, iv); byte[] decdata = NonMultipleOfBlockSize_Decrypt (decryptor, encdata); AssertEquals ("Decrypted Data Length", data.Length, decdata.Length); int i = 0; bool b = true; while (b && (i < data.Length)) { b = (data [i] == decdata [i]); i++; } Assert ("NonMultipleOfBlockSize", b); } // bugzilla: 51322 - indirectly related but it explains why my first (unapplied) patch didn't work [Test] public void DecryptPartial_TransformFinalBlock_required () { byte[] key = {0, 1, 2, 3, 4, 5, 6, 7}; byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7}; DES des = DES.Create (); byte[] data = Encoding.Unicode.GetBytes ("ximian"); // 12 bytes, 1.5 DES block size DebugStream encrypted = new DebugStream (); cs = new CryptoStream (encrypted, des.CreateEncryptor (key, iv), CryptoStreamMode.Write); cs.Write (data, 0, data.Length); cs.Close (); data = encrypted.ToArray (); DebugStream decrypted = new DebugStream (data); cs = new CryptoStream (decrypted, des.CreateDecryptor (key, iv), CryptoStreamMode.Read); int len = cs.Read (data, 0, data.Length); cs.Close (); AssertEquals ("Length", 12, len); AssertEquals ("Unicode DES Roundtrip", "ximian", Encoding.Unicode.GetString (data, 0, len)); } [Test] public void DecryptPartial_TransformFinalBlock_2Pass () { byte[] key = {0, 1, 2, 3, 4, 5, 6, 7}; byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7}; DES des = DES.Create (); byte[] data = Encoding.Unicode.GetBytes ("ximian"); // 12 bytes, 1.5 DES block size DebugStream encrypted = new DebugStream (); cs = new CryptoStream (encrypted, des.CreateEncryptor (key, iv), CryptoStreamMode.Write); cs.Write (data, 0, data.Length); cs.Close (); data = encrypted.ToArray (); DebugStream decrypted = new DebugStream (data); cs = new CryptoStream (decrypted, des.CreateDecryptor (key, iv), CryptoStreamMode.Read); int len = cs.Read (data, 0, 6); AssertEquals ("Length (1st pass)", 6, len); AssertEquals ("Partial DES Roundtrip", "xim", Encoding.Unicode.GetString (data, 0, len)); len += cs.Read (data, 6, 8); AssertEquals ("Length (1st+2nd)", 12, len); AssertEquals ("Full DES Roundtrip", "ximian", Encoding.Unicode.GetString (data, 0, len)); cs.Close (); } // based on http://www.c-sharpcorner.com/Code/2002/May/FileEncryption.asp [Test] public void WriteByteReadByte () { DebugStream original = new DebugStream (Encoding.Unicode.GetBytes ("ximian")); DebugStream encrypted = new DebugStream (); byte[] key = {0, 1, 2, 3, 4, 5, 6, 7}; byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7}; DES des = DES.Create (); cs = new CryptoStream (encrypted, des.CreateEncryptor (key, iv), CryptoStreamMode.Write); int data; while ((data = original.ReadByte ()) != -1) cs.WriteByte((byte) data); cs.Close (); byte[] result = encrypted.ToArray (); AssertEquals ("Encrypted", "18-EA-93-3F-20-86-D2-AA-78-02-D7-6F-E4-47-17-9C", BitConverter.ToString (result)); encrypted = new DebugStream (result); DebugStream decrypted = new DebugStream (); cs = new CryptoStream (encrypted, des.CreateDecryptor (key, iv), CryptoStreamMode.Read); while ((data = cs.ReadByte ()) != -1) decrypted.WriteByte((byte) data); cs.Close (); decrypted.Close (); AssertEquals ("W/R Byte Roundtrip", "ximian", Encoding.Unicode.GetString (decrypted.ToArray ())); } // based http://www.4guysfromrolla.com/webtech/090501-1.shtml public string EncryptData (ICryptoTransform des, string strData) { strData = String.Format("{0,5:00000}" + strData, strData.Length); byte[] data = Encoding.ASCII.GetBytes (strData); MemoryStream mStream = new MemoryStream (data); CryptoStream cs = new CryptoStream (mStream, des, CryptoStreamMode.Read); MemoryStream mOut = new MemoryStream (); int bytesRead; byte[] output = new byte [1024]; do { bytesRead = cs.Read (output, 0, 1024); if (bytesRead != 0) mOut.Write (output, 0, bytesRead); } while (bytesRead > 0); return Convert.ToBase64String (mOut.ToArray ()); } public string DecryptData (ICryptoTransform des, string strData) { MemoryStream mOut = new MemoryStream (); byte[] data = Convert.FromBase64String (strData); CryptoStream cs = new CryptoStream (mOut, des, CryptoStreamMode.Write); cs.Write (data, 0, (int)data.Length); cs.FlushFinalBlock (); return Encoding.ASCII.GetString (mOut.ToArray ()).Substring (5); } [Test] public void EncryptOnRead () { SHA1 sha = SHA1.Create (); byte[] vector = sha.ComputeHash (Encoding.ASCII.GetBytes ("s3kr3t")); byte[] key = new byte [8]; Buffer.BlockCopy (vector, 0, key, 0, key.Length); byte[] iv = new byte [8]; Buffer.BlockCopy (vector, 8, iv, 0, iv.Length); DES des = DES.Create (); StringBuilder sb = new StringBuilder (); sb.Append ("a"); string data = sb.ToString (); string encdata = EncryptData (des.CreateEncryptor (key, iv), data); string decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "9YVfvrh5yj0=", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "qNe4d0UlkU8=", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "OcernYAQ1NAME/Gny+ZuaA==", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "H5UveR2lds1T+IWN4pks2Q==", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "dDQ3HAVtTbiRwwUqWANaeA==", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "At1r7dVDjJlQidf4QzCNkw==", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "DFDJWJGaNrFVBDXovsq1ew==", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "gM040QGMPOBj3u1lEK4XHQ==", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "P5hRUhrxOWFX0ER/IjJL/Q==", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "uDIaQ1uXtWUIboGFLt306Q==", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "giJKTXfad5Z8hebhXtYZ4hmKX/EC8w6x", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "lBehBplIrjjrlIrMjYcNz1DOoXLHjZdn", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "2elWrUnjmsAOpo2s4voJyZXEJ/rtKB7P", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "GB3BaIZGf9K+T82j7T8Fri2rQ2/YUdSe", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "Gc+wkJL+CVjdJchgcIoi8dkH2BVpHJgB", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "loeuyII/PvWb91M4pFVkyaPxQoQVYpNb", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "PHXmi/sxNIgApXAfdm+Bf54/nCM//N8o", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "xpb+wj/8LmH2ScTg3OU4JOsE5Owj6flF", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "WJz4VfsZ2emzhYWoSf+PNBDpHooxEregqMWnzm4gcqU=", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "PaouZu1iOKbCMRJSu04y/kB+TcOk4yp8K2BOGDs1PPE=", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "qbTDs4dFy7eERdn5vV7JRPk2/m9smtwvZjA6+TmGlkI=", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "f2FsphcpM7Fu90S5V17ptly44lL4GvFCCaFdnnU4twk=", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "imD+ntHsUmp9ALJedzC1JmAJY0r2O4KkP8271+XuG4g=", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "80QLLUmHwx1fcEYGeFz1WXlS13kUy994sQLI6GhcjuM=", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "DtIIlj8BCOppmIgQ9AEdUj7pBB49S/9Q38kbWLjwiVs=", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "LNkprYaaUFtyan204OzX+a2pzOb/Pg5WXzXJ6WWB1rQ=", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "FRgx9m2lT2PxtYSIdRwc+SznJetNiRk1MEIZDl3D13pvo2yOtJ1MSQ==", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "V7JlnpJscrdIpX4z5S+/Q5WDjKzK4aB5TiqI3JZOYJ+KE1CWQNNeow==", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "wVwPv1c2KQynbwiOBCAhmQlReOQT52qFR34AX4dtjEeQ1oCQ1N1tHg==", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "Zi+G0yfmuFjSjP455pjVeKBDDWB4qvTb0K0h20UtflrYG6wcWqUzDw==", encdata); AssertEquals ("Decrypt-" + data, data, decdata); sb.Append ("a"); data = sb.ToString (); encdata = EncryptData (des.CreateEncryptor (key, iv), data); decdata = DecryptData (des.CreateDecryptor (key, iv), encdata); AssertEquals ("Encrypt-" + data, "0hGoonZ8jrLhMNDKBuWrlvFnq15ZLvnyq+Ilq8r4aYUEDxttQMwi5w==", encdata); AssertEquals ("Decrypt-" + data, data, decdata); } // based on System.Security assembly XmlDsigBase64TransformTest [Test] public void FromBase64_Write () { string expected = "http://www.go-mono.com/"; byte[] data = Encoding.UTF8.GetBytes (expected); string temp = Convert.ToBase64String (data, 0, data.Length); data = Encoding.UTF8.GetBytes (temp); DebugStream debug = new DebugStream (); ICryptoTransform base64 = new FromBase64Transform (); cs = new CryptoStream (debug, base64, CryptoStreamMode.Write); cs.Write (data, 0, data.Length); cs.FlushFinalBlock (); byte[] encoded = debug.ToArray (); string result = Encoding.UTF8.GetString (encoded); AssertEquals ("FromBase64_Write", expected, result); } [Test] public void FromBase64_Read () { byte[] original = Encoding.UTF8.GetBytes ("aHR0cDovL3d3dy5nby1tb25vLmNvbS8="); DebugStream debug = new DebugStream (original); ICryptoTransform base64 = new FromBase64Transform (); cs = new CryptoStream (debug, base64, CryptoStreamMode.Read); byte[] data = new byte [1024]; int length = cs.Read (data, 0, data.Length); cs.Close (); string result = Encoding.UTF8.GetString (data, 0, length); AssertEquals ("ToBase64_Read", "http://www.go-mono.com/", result); } [Test] public void ToBase64_Write () { byte[] data = Encoding.UTF8.GetBytes ("http://www.go-mono.com/"); DebugStream debug = new DebugStream (); ICryptoTransform base64 = new ToBase64Transform (); cs = new CryptoStream (debug, base64, CryptoStreamMode.Write); cs.Write (data, 0, data.Length); cs.FlushFinalBlock (); byte[] encoded = debug.ToArray (); string result = Encoding.UTF8.GetString (encoded); AssertEquals ("ToBase64_Write", "aHR0cDovL3d3dy5nby1tb25vLmNvbS8=", result); } [Test] public void ToBase64_Read () { byte[] original = Encoding.UTF8.GetBytes ("http://www.go-mono.com/"); DebugStream debug = new DebugStream (original); ICryptoTransform base64 = new ToBase64Transform (); cs = new CryptoStream (debug, base64, CryptoStreamMode.Read); byte[] data = new byte [1024]; int length = cs.Read (data, 0, data.Length); cs.Close (); string result = Encoding.UTF8.GetString (data, 0, length); AssertEquals ("ToBase64_Read", "aHR0cDovL3d3dy5nby1tb25vLmNvbS8=", result); } // Cascaded CryptoStream - like sample in book .NET Framework Security, chapter 30 [Test] public void CascadedCryptoStream_Write () { DebugStream debug = new DebugStream (); // calculate both the hash (before encryption) and encrypt in one Write operation byte[] key = {0, 1, 2, 3, 4, 5, 6, 7}; byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7}; DES des = DES.Create (); CryptoStream cse = new CryptoStream (debug, des.CreateEncryptor (key, iv), CryptoStreamMode.Write); MD5 hash = MD5.Create (); CryptoStream csh = new CryptoStream (cse, hash, CryptoStreamMode.Write); byte[] data = Encoding.UTF8.GetBytes ("http://www.go-mono.com/"); csh.Write (data, 0, data.Length); csh.FlushFinalBlock (); byte[] result = debug.ToArray (); AssertEquals ("Encrypted", "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)); byte[] digest = hash.Hash; AssertEquals ("Hash", "71-04-12-D1-95-01-CF-F9-8D-8F-F8-0D-F9-AA-11-7D", BitConverter.ToString (digest)); } [Test] public void CascadedCryptoStream_Read () { 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 }; DebugStream debug = new DebugStream (encdata); // decrypt data and validate its hash in one Read operation byte[] key = {0, 1, 2, 3, 4, 5, 6, 7}; byte[] iv = {0, 1, 2, 3, 4, 5, 6, 7}; DES des = DES.Create (); CryptoStream csd = new CryptoStream (debug, des.CreateDecryptor (key, iv), CryptoStreamMode.Read); MD5 hash = MD5.Create (); CryptoStream csh = new CryptoStream (csd, hash, CryptoStreamMode.Read); byte[] data = new byte [1024]; int length = csh.Read (data, 0, data.Length); csh.Close (); string result = Encoding.UTF8.GetString (data, 0, length); AssertEquals ("Decrypted", "http://www.go-mono.com/", result); byte[] digest = hash.Hash; AssertEquals ("Hash Validation", "71-04-12-D1-95-01-CF-F9-8D-8F-F8-0D-F9-AA-11-7D", BitConverter.ToString (digest)); } } }