Welcome to MSDN Blogs Sign in | Join | Help

ROT 128 Stream Upgrade Sample, Part 1

The mission for the next five days is to build and demonstrate an implementation of a stream upgrade. For review, a stream upgrade is a component that plugs into the transport and rewrites the byte stream as it goes on and off of the network. Stream upgrades are stackable and composable. You add stream upgrades by including stream upgrade binding elements in the desired order in the binding. I went over the basics of stream upgrades a few weeks ago. Here are the articles in that series:

  1. Stream Upgrades, Part 1
  2. Stream Upgrades, Part 2
  3. Stream Upgrades, Part 3

The example I've picked out is a stream upgrade that applies ROT 128 (ROTate by 128). ROT 13 is a famous example of a Caesar cipher that occludes messages by replacing letters in the English alphabet with the letter that is 13 places higher. When you go past 'Z', you wrap back around to 'A'. Since there are 26 letters, applying ROT 13 twice returns a letter back to where it started. ROT 128 is the equivalent for a single byte value.

Here is the stream class that I want to have my messages run through. It includes some debugging so that we can see the messages as they go in and out.

using System;
using System.IO;

namespace Microsoft.ServiceModel.Samples
{
class ROT128Stream : Stream
{
Stream stream;

public ROT128Stream(Stream stream)
{
this.stream = stream;
}

public override bool CanRead
{
get { return this.stream.CanRead; }
}

public override bool CanSeek
{
get { return this.stream.CanSeek; }
}

public override bool CanWrite
{
get { return this.stream.CanWrite; }
}

protected override void Dispose(bool disposing)
{
if (disposing)
{
this.stream.Dispose();
}
else { this.stream.Close();
}
base.Dispose(disposing);
}

public override void Flush()
{
this.stream.Flush();
}

public override long Length
{
get { return this.stream.Length; }
}

public override long Position
{
get
{
return this.stream.Position;
}
set
{
this.stream.Position = value;
}
}

static void DumpBuffer(byte[] buffer, int offset, int count)
{
int pos = 0;
while (pos < count)
{
int lineCount = count - pos;
if (lineCount > 15)
{
lineCount = 15;
}
for (int linePos = 0; linePos < lineCount; linePos++)
{
Console.Write(" {0:X2}", buffer[offset + pos + linePos]);
}
for (int linePos = 15 - lineCount; linePos >= 0; linePos--)
{
Console.Write(" ");
}
for (int linePos = 0; linePos < lineCount; linePos++)
{
byte item = buffer[offset + pos + linePos];
if (item < 0x20 || item >= 0x80)
{
Console.Write(".");
}
else { Console.Write((char)item);
}
}
Console.WriteLine();
pos += lineCount;
}
}

public override int Read(byte[] buffer, int offset, int count)
{
int result = this.stream.Read(buffer, offset, count);
Console.WriteLine("[READ] {0} bytes", result);
DumpBuffer(buffer, offset, result);
for (int pos = 0; pos < result; pos++)
{
buffer[pos + offset] ^= 0x80;
}
return result;
}

public override long Seek(long offset, SeekOrigin origin)
{
return this.stream.Seek(offset, origin);
}

public override void SetLength(long value)
{
this.stream.SetLength(value);
}

public override void Write(byte[] buffer, int offset, int count)
{
Console.WriteLine("[WRITE] {0} bytes", count);
DumpBuffer(buffer, offset, count);
byte[] encodedBuffer = new byte[count];
for (int pos = 0; pos < count; pos++)
{
encodedBuffer[pos] = (byte)(buffer[pos + offset] ^ 0x80);
}
this.stream.Write(encodedBuffer, 0, count);
}
}
}

Next time: ROT 128 Stream Upgrade Sample, Part 2

Published Wednesday, September 27, 2006 5:00 AM by Nicholas Allen

Comments

Wednesday, September 27, 2006 10:19 AM by Orion Adrian

# re: ROT 128 Stream Upgrade Sample, Part 1

My question is why do you encapsulate a Stream object while also inheriting from Stream? Wouldn't this example be a lot simpler if you just inherited from Stream?
Wednesday, September 27, 2006 11:21 AM by Nicholas Paldino [.NET/C# MVP]

# re: ROT 128 Stream Upgrade Sample, Part 1

Nick,

You need to change your override of the Dispose method.  Right now, you are calling Close if disposing is true, and Dispose otherwise.  However, they are the same call (Dispose calls Close)!

You should just check to see if disposing is true, and if so, call Dispose, nothing more, nothing less.
Wednesday, September 27, 2006 12:03 PM by Nicholas Allen's Indigo Blog

# Math Behind the RSA Algorithm

This post is to tie up some loose ends in regards to actually performing the RSA computations.  I've...
Wednesday, September 27, 2006 4:13 PM by Nicholas Allen

# re: ROT 128 Stream Upgrade Sample, Part 1

Orion-

The point of this Stream class is to transform the stream we get from the transport.  The Stream parameter is the old stream and the inherited Stream is going to be the new stream.
Wednesday, September 27, 2006 4:16 PM by Nicholas Allen

# re: ROT 128 Stream Upgrade Sample, Part 1

Nicholas-

I was just being lazy and didn't take the time to override Close and Dispose separately.  I also didn't override the timeouts or async methods.  For the purposes of this example, it doesn't actually make a difference.
Wednesday, October 04, 2006 12:07 PM by Nicholas Allen's Indigo Blog

# ROT 128 Stream Upgrade Sample, Part 5

Today is the last part of the stream upgrade sample. We’ve already looked at all the parts required to

Wednesday, October 04, 2006 1:38 PM by Nicholas Allen's Indigo Blog

# ROT 128 Stream Upgrade Sample, Part 4

The final pieces needed for the ROT 128 sample are a stream upgrade initiator and a stream upgrade acceptor.

New Comments to this post are disabled
 
Page view tracker