diff --git a/Crypto/src/crypto/io/CipherStream.cs b/Crypto/src/crypto/io/CipherStream.cs
new file mode 100644
index 000000000..bf7effb0a
--- /dev/null
+++ b/Crypto/src/crypto/io/CipherStream.cs
@@ -0,0 +1,237 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+
+namespace Org.BouncyCastle.Crypto.IO
+{
+ public class CipherStream
+ : Stream
+ {
+ internal Stream stream;
+ internal IBufferedCipher inCipher, outCipher;
+ private byte[] mInBuf;
+ private int mInPos;
+ private bool inStreamEnded;
+
+ public CipherStream(
+ Stream stream,
+ IBufferedCipher readCipher,
+ IBufferedCipher writeCipher)
+ {
+ this.stream = stream;
+
+ if (readCipher != null)
+ {
+ this.inCipher = readCipher;
+ mInBuf = null;
+ }
+
+ if (writeCipher != null)
+ {
+ this.outCipher = writeCipher;
+ }
+ }
+
+ public IBufferedCipher ReadCipher
+ {
+ get { return inCipher; }
+ }
+
+ public IBufferedCipher WriteCipher
+ {
+ get { return outCipher; }
+ }
+
+ public override int ReadByte()
+ {
+ if (inCipher == null)
+ return stream.ReadByte();
+
+ if (mInBuf == null || mInPos >= mInBuf.Length)
+ {
+ if (!FillInBuf())
+ return -1;
+ }
+
+ return mInBuf[mInPos++];
+ }
+
+ public override int Read(
+ byte[] buffer,
+ int offset,
+ int count)
+ {
+ if (inCipher == null)
+ return stream.Read(buffer, offset, count);
+
+ int num = 0;
+ while (num < count)
+ {
+ if (mInBuf == null || mInPos >= mInBuf.Length)
+ {
+ if (!FillInBuf())
+ break;
+ }
+
+ int numToCopy = System.Math.Min(count - num, mInBuf.Length - mInPos);
+ Array.Copy(mInBuf, mInPos, buffer, offset + num, numToCopy);
+ mInPos += numToCopy;
+ num += numToCopy;
+ }
+
+ return num;
+ }
+
+ private bool FillInBuf()
+ {
+ if (inStreamEnded)
+ return false;
+
+ mInPos = 0;
+
+ do
+ {
+ mInBuf = ReadAndProcessBlock();
+ }
+ while (!inStreamEnded && mInBuf == null);
+
+ return mInBuf != null;
+ }
+
+ private byte[] ReadAndProcessBlock()
+ {
+ int blockSize = inCipher.GetBlockSize();
+ int readSize = (blockSize == 0) ? 256 : blockSize;
+
+ byte[] block = new byte[readSize];
+ int numRead = 0;
+ do
+ {
+ int count = stream.Read(block, numRead, block.Length - numRead);
+ if (count < 1)
+ {
+ inStreamEnded = true;
+ break;
+ }
+ numRead += count;
+ }
+ while (numRead < block.Length);
+
+ Debug.Assert(inStreamEnded || numRead == block.Length);
+
+ byte[] bytes = inStreamEnded
+ ? inCipher.DoFinal(block, 0, numRead)
+ : inCipher.ProcessBytes(block);
+
+ if (bytes != null && bytes.Length == 0)
+ {
+ bytes = null;
+ }
+
+ return bytes;
+ }
+
+ public override void Write(
+ byte[] buffer,
+ int offset,
+ int count)
+ {
+ Debug.Assert(buffer != null);
+ Debug.Assert(0 <= offset && offset <= buffer.Length);
+ Debug.Assert(count >= 0);
+
+ int end = offset + count;
+
+ Debug.Assert(0 <= end && end <= buffer.Length);
+
+ if (outCipher == null)
+ {
+ stream.Write(buffer, offset, count);
+ return;
+ }
+
+ byte[] data = outCipher.ProcessBytes(buffer, offset, count);
+ if (data != null)
+ {
+ stream.Write(data, 0, data.Length);
+ }
+ }
+
+ public override void WriteByte(
+ byte b)
+ {
+ if (outCipher == null)
+ {
+ stream.WriteByte(b);
+ return;
+ }
+
+ byte[] data = outCipher.ProcessByte(b);
+ if (data != null)
+ {
+ stream.Write(data, 0, data.Length);
+ }
+ }
+
+ public override bool CanRead
+ {
+ get { return stream.CanRead && (inCipher != null); }
+ }
+
+ public override bool CanWrite
+ {
+ get { return stream.CanWrite && (outCipher != null); }
+ }
+
+ public override bool CanSeek
+ {
+ get { return false; }
+ }
+
+ public sealed override long Length
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public sealed override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (outCipher != null)
+ {
+ byte[] data = outCipher.DoFinal();
+ stream.Write(data, 0, data.Length);
+ stream.Flush();
+ }
+ stream.Dispose();
+ }
+ }
+
+ public override void Flush()
+ {
+ // Note: outCipher.DoFinal is only called during Close()
+ stream.Flush();
+ }
+
+ public sealed override long Seek(
+ long offset,
+ SeekOrigin origin)
+ {
+ throw new NotSupportedException();
+ }
+
+ public sealed override void SetLength(
+ long length)
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
diff --git a/Crypto/src/crypto/io/DigestStream.cs b/Crypto/src/crypto/io/DigestStream.cs
new file mode 100644
index 000000000..a5b31f95c
--- /dev/null
+++ b/Crypto/src/crypto/io/DigestStream.cs
@@ -0,0 +1,140 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.IO
+{
+ public class DigestStream
+ : Stream
+ {
+ protected readonly Stream stream;
+ protected readonly IDigest inDigest;
+ protected readonly IDigest outDigest;
+
+ public DigestStream(
+ Stream stream,
+ IDigest readDigest,
+ IDigest writeDigest)
+ {
+ this.stream = stream;
+ this.inDigest = readDigest;
+ this.outDigest = writeDigest;
+ }
+
+ public virtual IDigest ReadDigest()
+ {
+ return inDigest;
+ }
+
+ public virtual IDigest WriteDigest()
+ {
+ return outDigest;
+ }
+
+ public override int Read(
+ byte[] buffer,
+ int offset,
+ int count)
+ {
+ int n = stream.Read(buffer, offset, count);
+ if (inDigest != null)
+ {
+ if (n > 0)
+ {
+ inDigest.BlockUpdate(buffer, offset, n);
+ }
+ }
+ return n;
+ }
+
+ public override int ReadByte()
+ {
+ int b = stream.ReadByte();
+ if (inDigest != null)
+ {
+ if (b >= 0)
+ {
+ inDigest.Update((byte)b);
+ }
+ }
+ return b;
+ }
+
+ public override void Write(
+ byte[] buffer,
+ int offset,
+ int count)
+ {
+ if (outDigest != null)
+ {
+ if (count > 0)
+ {
+ outDigest.BlockUpdate(buffer, offset, count);
+ }
+ }
+ stream.Write(buffer, offset, count);
+ }
+
+ public override void WriteByte(
+ byte b)
+ {
+ if (outDigest != null)
+ {
+ outDigest.Update(b);
+ }
+ stream.WriteByte(b);
+ }
+
+ public override bool CanRead
+ {
+ get { return stream.CanRead; }
+ }
+
+ public override bool CanWrite
+ {
+ get { return stream.CanWrite; }
+ }
+
+ public override bool CanSeek
+ {
+ get { return stream.CanSeek; }
+ }
+
+ public override long Length
+ {
+ get { return stream.Length; }
+ }
+
+ public override long Position
+ {
+ get { return stream.Position; }
+ set { stream.Position = value; }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ stream.Dispose();
+ }
+ }
+
+ public override void Flush()
+ {
+ stream.Flush();
+ }
+
+ public override long Seek(
+ long offset,
+ SeekOrigin origin)
+ {
+ return stream.Seek(offset, origin);
+ }
+
+ public override void SetLength(
+ long length)
+ {
+ stream.SetLength(length);
+ }
+ }
+}
+
diff --git a/Crypto/src/crypto/io/MacStream.cs b/Crypto/src/crypto/io/MacStream.cs
new file mode 100644
index 000000000..419eafb77
--- /dev/null
+++ b/Crypto/src/crypto/io/MacStream.cs
@@ -0,0 +1,139 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.IO
+{
+ public class MacStream
+ : Stream
+ {
+ protected readonly Stream stream;
+ protected readonly IMac inMac;
+ protected readonly IMac outMac;
+
+ public MacStream(
+ Stream stream,
+ IMac readMac,
+ IMac writeMac)
+ {
+ this.stream = stream;
+ this.inMac = readMac;
+ this.outMac = writeMac;
+ }
+
+ public virtual IMac ReadMac()
+ {
+ return inMac;
+ }
+
+ public virtual IMac WriteMac()
+ {
+ return outMac;
+ }
+
+ public override int Read(
+ byte[] buffer,
+ int offset,
+ int count)
+ {
+ int n = stream.Read(buffer, offset, count);
+ if (inMac != null)
+ {
+ if (n > 0)
+ {
+ inMac.BlockUpdate(buffer, offset, n);
+ }
+ }
+ return n;
+ }
+
+ public override int ReadByte()
+ {
+ int b = stream.ReadByte();
+ if (inMac != null)
+ {
+ if (b >= 0)
+ {
+ inMac.Update((byte)b);
+ }
+ }
+ return b;
+ }
+
+ public override void Write(
+ byte[] buffer,
+ int offset,
+ int count)
+ {
+ if (outMac != null)
+ {
+ if (count > 0)
+ {
+ outMac.BlockUpdate(buffer, offset, count);
+ }
+ }
+ stream.Write(buffer, offset, count);
+ }
+
+ public override void WriteByte(byte b)
+ {
+ if (outMac != null)
+ {
+ outMac.Update(b);
+ }
+ stream.WriteByte(b);
+ }
+
+ public override bool CanRead
+ {
+ get { return stream.CanRead; }
+ }
+
+ public override bool CanWrite
+ {
+ get { return stream.CanWrite; }
+ }
+
+ public override bool CanSeek
+ {
+ get { return stream.CanSeek; }
+ }
+
+ public override long Length
+ {
+ get { return stream.Length; }
+ }
+
+ public override long Position
+ {
+ get { return stream.Position; }
+ set { stream.Position = value; }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ stream.Dispose();
+ }
+ }
+
+ public override void Flush()
+ {
+ stream.Flush();
+ }
+
+ public override long Seek(
+ long offset,
+ SeekOrigin origin)
+ {
+ return stream.Seek(offset,origin);
+ }
+
+ public override void SetLength(
+ long length)
+ {
+ stream.SetLength(length);
+ }
+ }
+}
+
diff --git a/Crypto/src/crypto/io/SignerStream.cs b/Crypto/src/crypto/io/SignerStream.cs
new file mode 100644
index 000000000..8be8ca84a
--- /dev/null
+++ b/Crypto/src/crypto/io/SignerStream.cs
@@ -0,0 +1,140 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.IO
+{
+ public class SignerStream
+ : Stream
+ {
+ protected readonly Stream stream;
+ protected readonly ISigner inSigner;
+ protected readonly ISigner outSigner;
+
+ public SignerStream(
+ Stream stream,
+ ISigner readSigner,
+ ISigner writeSigner)
+ {
+ this.stream = stream;
+ this.inSigner = readSigner;
+ this.outSigner = writeSigner;
+ }
+
+ public virtual ISigner ReadSigner()
+ {
+ return inSigner;
+ }
+
+ public virtual ISigner WriteSigner()
+ {
+ return outSigner;
+ }
+
+ public override int Read(
+ byte[] buffer,
+ int offset,
+ int count)
+ {
+ int n = stream.Read(buffer, offset, count);
+ if (inSigner != null)
+ {
+ if (n > 0)
+ {
+ inSigner.BlockUpdate(buffer, offset, n);
+ }
+ }
+ return n;
+ }
+
+ public override int ReadByte()
+ {
+ int b = stream.ReadByte();
+ if (inSigner != null)
+ {
+ if (b >= 0)
+ {
+ inSigner.Update((byte)b);
+ }
+ }
+ return b;
+ }
+
+ public override void Write(
+ byte[] buffer,
+ int offset,
+ int count)
+ {
+ if (outSigner != null)
+ {
+ if (count > 0)
+ {
+ outSigner.BlockUpdate(buffer, offset, count);
+ }
+ }
+ stream.Write(buffer, offset, count);
+ }
+
+ public override void WriteByte(
+ byte b)
+ {
+ if (outSigner != null)
+ {
+ outSigner.Update(b);
+ }
+ stream.WriteByte(b);
+ }
+
+ public override bool CanRead
+ {
+ get { return stream.CanRead; }
+ }
+
+ public override bool CanWrite
+ {
+ get { return stream.CanWrite; }
+ }
+
+ public override bool CanSeek
+ {
+ get { return stream.CanSeek; }
+ }
+
+ public override long Length
+ {
+ get { return stream.Length; }
+ }
+
+ public override long Position
+ {
+ get { return stream.Position; }
+ set { stream.Position = value; }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ stream.Dispose();
+ }
+ }
+
+ public override void Flush()
+ {
+ stream.Flush();
+ }
+
+ public override long Seek(
+ long offset,
+ SeekOrigin origin)
+ {
+ return stream.Seek(offset, origin);
+ }
+
+ public override void SetLength(
+ long length)
+ {
+ stream.SetLength(length);
+ }
+ }
+}
+
|