[Mono-bugs] [Bug 60573][Nor] New - CryptoStream output 1 block short after Flush
bugzilla-daemon@bugzilla.ximian.com
bugzilla-daemon@bugzilla.ximian.com
Tue, 22 Jun 2004 13:27:04 -0400 (EDT)
Please do not reply to this email- if you want to comment on the bug, go to the
URL shown below and enter your comments there.
Changed by t7@pobox.com.
http://bugzilla.ximian.com/show_bug.cgi?id=60573
--- shadow/60573 2004-06-22 13:27:04.000000000 -0400
+++ shadow/60573.tmp.24951 2004-06-22 13:27:04.000000000 -0400
@@ -0,0 +1,215 @@
+Bug#: 60573
+Product: Mono: Class Libraries
+Version: unspecified
+OS:
+OS Details: Other
+Status: NEW
+Resolution:
+Severity:
+Priority: Normal
+Component: System.Security
+AssignedTo: mono-bugs@ximian.com
+ReportedBy: t7@pobox.com
+QAContact: mono-bugs@ximian.com
+TargetMilestone: ---
+URL:
+Cc:
+Summary: CryptoStream output 1 block short after Flush
+
+Please fill in this template when reporting a bug, unless you know what you
+are doing.
+Description of Problem:
+When a CryptoStream is created from an encryptor and a multiple of the
+block size is written to it. It outputs one block short after a Flush.
+
+System is Redhat Fedora Core 2 with kernel 2.6.5. Mono beta3 release.
+
+Steps to reproduce the problem:
+1. Compile and run the test code included
+2.
+3.
+
+Actual Results:
+outputs
+CryptoStreamOutput: Write(buffer, offset=0, count=56)
+CryptoStreamOutput: Flush()
+
+Expected Results:
+should output
+CryptoStreamOutput: Write(buffer, offset=0, count=64)
+CryptoStreamOutput: Flush()
+
+
+How often does this happen?
+Every time
+
+Additional Information:
+I think this is an implementation bug, but I'm new to the
+mono crypto API, so it could be a misunderstanding on my
+part.
+As you can see from the code, I instantiate a 3DES provided.
+This has a BlockSize of 64 by default. I create the encryptor
+via CreateEncryptor() and the resulting ICryptoTransform has
+an inpout/output block size of 8.
+So, when I write 64 bytes (a multiple of 8) to the crypto stream
+and do a flush, I'd expect 64 bytes out - but I only get 56
+(8 short). In my actual application there is a network stream
+between the encryptor and decryptor, but I always get blocked
+waiting for the block that never comes.
+Note also, that the block is not lost. Pushing another 64 bytes into
+the stream causes the missing 8 bytes to come out, followed by another
+56 bytes corresponding to the second 64 bytes (again, 8 short after the Flush).
+
+Here is the code. Not that the most part is just the impl of the
+DebugStream, which is just a pass-through stream to show what's
+happening. Omitting it and just using the few lines of Main
+without the DebugStream will also reproduce the problem.
+
+Hope this helps. Sorry if it isn't really a bug.
+
+
+using System;
+using System.IO;
+using System.Security.Cryptography;
+
+
+
+//
+// DebugStream is just a pass-through that displays the method call args
+//
+
+class DebugStream : Stream
+{
+ public DebugStream(Stream s, string name)
+ {
+ this.s = s;
+ this.name = name;
+ }
+
+
+ public bool disp = true; // display?
+ public string name = "DebugStream";
+
+
+ public override bool CanRead { get {return s.CanRead;} }
+ public override bool CanSeek { get {return s.CanSeek;} }
+ public override bool CanWrite { get {return s.CanWrite;} }
+ public override long Length { get {return s.Length;} }
+ public override long Position { get {return s.Position;} set
+{s.Position=value;} }
+
+ public override void Close () { s.Close(); }
+
+
+ public override void Flush ()
+ {
+ if (disp) Console.WriteLine(name+": Flush()");
+ s.Flush();
+ }
+
+ public override int Read (byte[] buffer, int offset, int count)
+ {
+ if (disp) Console.Write(name+": Read(buffer, offset="+offset+",
+count="+count+")");
+ int res = s.Read(buffer, offset, count);
+ if (disp) Console.WriteLine(" -> "+res);
+ return res;
+ }
+
+ public override int ReadByte ()
+ {
+ if (disp) Console.Write(name+": ReadByte()");
+ int res = s.ReadByte();
+ if (disp) Console.WriteLine(" -> "+res);
+ return res;
+ }
+
+ public override long Seek (long offset, SeekOrigin origin) { return
+s.Seek(offset, origin); }
+
+ public override void SetLength (long value) { s.SetLength(value); }
+
+ public override void Write (byte[] buffer, int offset, int count)
+ {
+ if (disp) Console.WriteLine(name+": Write(buffer, offset="+offset+",
+count="+count+")");
+ s.Write(buffer, offset, count);
+ }
+
+ public override void WriteByte (byte value)
+ {
+ if (disp) Console.WriteLine(name+": WriteByte(value="+value+")");
+ s.WriteByte(value);
+ }
+
+ public override IAsyncResult
+ BeginRead (byte [] buffer, int offset, int count, AsyncCallback cback,
+object state)
+ {
+ if (disp) Console.WriteLine(name+": BeginRead(buffer, offset, count,
+cback, state)");
+ return s.BeginRead(buffer, offset, count, cback, state);
+ }
+
+
+ public override IAsyncResult
+ BeginWrite (byte [] buffer, int offset, int count, AsyncCallback cback,
+object state)
+ {
+ if (disp) Console.WriteLine(name+": BeginWrite(buffer, offset, count,
+cback, state)");
+ return s.BeginWrite(buffer, offset, count, cback, state);
+ }
+
+ public override int EndRead (IAsyncResult async_result)
+ {
+ if (disp) Console.WriteLine(name+": EndRead(async_result)");
+ return s.EndRead(async_result);
+ }
+
+ public override void EndWrite (IAsyncResult async_result)
+ {
+ if (disp) Console.WriteLine(name+": EndWrite(async_result)");
+ s.EndWrite(async_result);
+ }
+
+
+ protected Stream s;
+
+}
+
+
+
+
+
+public class CryptoTest
+{
+
+ // 64 bytes
+ static public byte[] data =
+System.Text.Encoding.ASCII.GetBytes("0123456789012345678901234567890123456789012345678901234567890123");
+
+ public static void Main(string[] args)
+ {
+
+ TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
+ tdes.GenerateKey();
+ tdes.GenerateIV();
+
+ // wrap a DebugStream around Stream.Null so we can see what calls
+CryptoStream makes to it's underlying Stream
+ DebugStream outDebugStream = new DebugStream(Stream.Null,
+"CryptoStreamOutput");
+
+ // feed that with a CryptoStream
+ CryptoStream encStream = new CryptoStream(outDebugStream,
+tdes.CreateEncryptor(), CryptoStreamMode.Write);
+
+
+ // feed some data to the crypto stream
+ encStream.Write(data,0,64); // 64 bytes out
+ encStream.Flush();
+
+ }
+
+}