olegkap_cp 14 роки тому
батько
коміт
e369b0f53e

+ 26 - 8
Renci.SshClient/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj

@@ -417,6 +417,9 @@
     <Compile Include="..\Renci.SshNet\Security\CipherTripleDesCbc.cs">
       <Link>Security\CipherTripleDesCbc.cs</Link>
     </Compile>
+    <Compile Include="..\Renci.SshNet\Security\Cryptography\AsymmetricCipher.cs">
+      <Link>Security\Cryptography\AsymmetricCipher.cs</Link>
+    </Compile>
     <Compile Include="..\Renci.SshNet\Security\Cryptography\Ciphers\AesCipher.cs">
       <Link>Security\Cryptography\Ciphers\AesCipher.cs</Link>
     </Compile>
@@ -441,11 +444,14 @@
     <Compile Include="..\Renci.SshNet\Security\Cryptography\Ciphers\TwofishCipher.cs">
       <Link>Security\Cryptography\Ciphers\TwofishCipher.cs</Link>
     </Compile>
+    <Compile Include="..\Renci.SshNet\Security\Cryptography\DigitalSignature.cs">
+      <Link>Security\Cryptography\DigitalSignature.cs</Link>
+    </Compile>
     <Compile Include="..\Renci.SshNet\Security\Cryptography\HMAC.cs">
       <Link>Security\Cryptography\HMAC.cs</Link>
     </Compile>
-    <Compile Include="..\Renci.SshNet\Security\Cryptography\MD5.cs">
-      <Link>Security\Cryptography\MD5.cs</Link>
+    <Compile Include="..\Renci.SshNet\Security\Cryptography\MD5Hash.cs">
+      <Link>Security\Cryptography\MD5Hash.cs</Link>
     </Compile>
     <Compile Include="..\Renci.SshNet\Security\Cryptography\Modes\CbcMode.cs">
       <Link>Security\Cryptography\Modes\CbcMode.cs</Link>
@@ -465,24 +471,36 @@
     <Compile Include="..\Renci.SshNet\Security\Cryptography\Modes\OfbMode.cs">
       <Link>Security\Cryptography\Modes\OfbMode.cs</Link>
     </Compile>
+    <Compile Include="..\Renci.SshNet\Security\Cryptography\RSACipher.cs">
+      <Link>Security\Cryptography\RSACipher.cs</Link>
+    </Compile>
+    <Compile Include="..\Renci.SshNet\Security\Cryptography\RSADigitalSignature.cs">
+      <Link>Security\Cryptography\RSADigitalSignature.cs</Link>
+    </Compile>
+    <Compile Include="..\Renci.SshNet\Security\Cryptography\RSAPrivateKey.cs">
+      <Link>Security\Cryptography\RSAPrivateKey.cs</Link>
+    </Compile>
+    <Compile Include="..\Renci.SshNet\Security\Cryptography\RSAPublicKey.cs">
+      <Link>Security\Cryptography\RSAPublicKey.cs</Link>
+    </Compile>
+    <Compile Include="..\Renci.SshNet\Security\Cryptography\SHA1Hash.cs">
+      <Link>Security\Cryptography\SHA1Hash.cs</Link>
+    </Compile>
+    <Compile Include="..\Renci.SshNet\Security\Cryptography\SHA256Hash.cs">
+      <Link>Security\Cryptography\SHA256Hash.cs</Link>
+    </Compile>
     <Compile Include="..\Renci.SshNet\Security\CryptoKey.cs">
       <Link>Security\CryptoKey.cs</Link>
     </Compile>
     <Compile Include="..\Renci.SshNet\Security\CryptoPrivateKey.cs">
       <Link>Security\CryptoPrivateKey.cs</Link>
     </Compile>
-    <Compile Include="..\Renci.SshNet\Security\CryptoPrivateKeyDss.cs">
-      <Link>Security\CryptoPrivateKeyDss.cs</Link>
-    </Compile>
     <Compile Include="..\Renci.SshNet\Security\CryptoPrivateKeyRsa.cs">
       <Link>Security\CryptoPrivateKeyRsa.cs</Link>
     </Compile>
     <Compile Include="..\Renci.SshNet\Security\CryptoPublicKey.cs">
       <Link>Security\CryptoPublicKey.cs</Link>
     </Compile>
-    <Compile Include="..\Renci.SshNet\Security\CryptoPublicKeyDss.cs">
-      <Link>Security\CryptoPublicKeyDss.cs</Link>
-    </Compile>
     <Compile Include="..\Renci.SshNet\Security\CryptoPublicKeyRsa.cs">
       <Link>Security\CryptoPublicKeyRsa.cs</Link>
     </Compile>

+ 0 - 19
Renci.SshClient/Renci.SshNet/Common/BigInteger.cs

@@ -79,25 +79,6 @@ namespace Renci.SshNet.Common
         private readonly uint[] _data;
         private readonly short _sign;
 
-        public int NumberOfBits
-        {
-            get
-            {
-                var lastByte = this._data[this._data.Length - 1];
-                if (this._sign < 0)
-                    lastByte = ~lastByte;
-                var counter = 32;
-                var t = 2147483648;
-                for (; counter > 0; counter--)
-                {
-                    if ((lastByte & t) > 0)
-                        break;
-                    t >>= 1;
-                }
-                return (this._data.Length - 1) * 32 + counter;
-            }
-        }
-
         #region Constractors
 
         /// <summary>

+ 5 - 1
Renci.SshClient/Renci.SshNet/Common/Extensions.cs

@@ -78,6 +78,9 @@ namespace Renci.SshNet
             return IsEqualTo(value, compareList, null);
         }
 
+#if SILVERLIGHT
+#else
+
         /// <summary>
         /// Prints out 
         /// </summary>
@@ -90,6 +93,7 @@ namespace Renci.SshNet
             }
             Debug.WriteLine(string.Empty);
         }
+#endif
 
         /// <summary>
         /// Trims the leading zero from bytes array.
@@ -169,7 +173,7 @@ namespace Renci.SshNet
 
 #if SILVERLIGHT
         private static Regex _rehost = new Regex(@"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$", RegexOptions.IgnoreCase);
-        
+
         private static Regex _reIPv6 = new Regex(@"^(((?=(?>.*?::)(?!.*::)))(::)?([0-9A-F]{1,4}::?){0,5}|([0-9A-F]{1,4}:){6})(\2([0-9A-F]{1,4}(::?|$)){0,2}|((25[0-5]|(2[0-4]|1\d|[1-9])?\d)(\.|$)){4}|[0-9A-F]{1,4}:[0-9A-F]{1,4})(?<![^:]:|\.)\z", RegexOptions.IgnoreCase);
 #else
         private static Regex _rehost = new Regex(@"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$", RegexOptions.IgnoreCase | RegexOptions.Compiled);

+ 1 - 1
Renci.SshClient/Renci.SshNet/PasswordConnectionInfo.cs

@@ -59,7 +59,7 @@ namespace Renci.SshNet
         /// <param name="password">Connection password.</param>
         /// <exception cref="ArgumentNullException"><paramref name="password"/> is null.</exception>
         /// <exception cref="ArgumentException"><paramref name="host"/> is invalid, or <paramref name="username"/> is null or contains whitespace characters.</exception>
-        /// <exception cref="ArgumentOutOfRangeException"><paramref name="port"/> is not within <see cref="IPEndPoint.MinPort"/> and <see cref="IPEndPoint.MaxPort"/>.</exception>
+        /// <exception cref="ArgumentOutOfRangeException"><paramref name="port"/> is not within <see cref="f:IPEndPoint.MinPort"/> and <see cref="f:IPEndPoint.MaxPort"/>.</exception>
         public PasswordConnectionInfo(string host, int port, string username, string password)
             : base(host, port, username)
         {

+ 3 - 1
Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj

@@ -157,7 +157,9 @@
     <Compile Include="Security\Cryptography\SHA1Hash.cs">
       <SubType>Code</SubType>
     </Compile>
-    <Compile Include="Security\Cryptography\SHA256Hash.cs" />
+    <Compile Include="Security\Cryptography\SHA256Hash.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="Security\CryptoKey.cs">
       <SubType>Code</SubType>
     </Compile>

+ 13 - 0
Renci.SshClient/Renci.SshNet/Security/Cryptography/AsymmetricCipher.cs

@@ -6,10 +6,23 @@ using Renci.SshNet.Common;
 
 namespace Renci.SshNet.Security.Cryptography
 {
+    /// <summary>
+    /// Base class for asymmetric cipher implementation
+    /// </summary>
     public abstract class AsymmetricCipher
     {
+        /// <summary>
+        /// Transforms the specified input.
+        /// </summary>
+        /// <param name="input">The input.</param>
+        /// <returns></returns>
         public abstract byte[] Transform(byte[] input);
 
+        /// <summary>
+        /// Transforms the specified input.
+        /// </summary>
+        /// <param name="input">The input.</param>
+        /// <returns></returns>
         public abstract BigInteger Transform(BigInteger input);
     }
 }

+ 14 - 0
Renci.SshClient/Renci.SshNet/Security/Cryptography/DigitalSignature.cs

@@ -6,10 +6,24 @@ using System.Security.Cryptography;
 
 namespace Renci.SshNet.Security.Cryptography
 {
+    /// <summary>
+    /// Base class for signature implementations
+    /// </summary>
     public abstract class DigitalSignature
     {
+        /// <summary>
+        /// Verifies the signature.
+        /// </summary>
+        /// <param name="input">The input.</param>
+        /// <param name="signature">The signature.</param>
+        /// <returns></returns>
         public abstract bool VerifySignature(byte[] input, byte[] signature);
 
+        /// <summary>
+        /// Creates the signature.
+        /// </summary>
+        /// <param name="input">The input.</param>
+        /// <returns></returns>
         public abstract byte[] CreateSignature(byte[] input);
     }
 }

+ 18 - 0
Renci.SshClient/Renci.SshNet/Security/Cryptography/RSACipher.cs

@@ -7,17 +7,30 @@ using Renci.SshNet.Common;
 
 namespace Renci.SshNet.Security.Cryptography
 {
+    /// <summary>
+    /// RSA algorithm implementation
+    /// </summary>
     public class RSACipher : AsymmetricCipher
     {
         private static RNGCryptoServiceProvider _randomizer = new System.Security.Cryptography.RNGCryptoServiceProvider();
 
         private RSAPublicKey _key;
 
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RSACipher"/> class.
+        /// </summary>
+        /// <param name="hash">The hash.</param>
+        /// <param name="key">The key.</param>
         public RSACipher(HashAlgorithm hash, RSAPublicKey key)
         {
             this._key = key;
         }
 
+        /// <summary>
+        /// Transforms the specified data.
+        /// </summary>
+        /// <param name="data">The data.</param>
+        /// <returns></returns>
         public override byte[] Transform(byte[] data)
         {
             var bytes = new List<byte>(data.Reverse());
@@ -25,6 +38,11 @@ namespace Renci.SshNet.Security.Cryptography
             return this.Transform(new BigInteger(bytes.ToArray())).ToByteArray().Reverse().ToArray();
         }
 
+        /// <summary>
+        /// Transforms the specified input.
+        /// </summary>
+        /// <param name="input">The input.</param>
+        /// <returns></returns>
         public override BigInteger Transform(BigInteger input)
         {
             var privateKey = this._key as RSAPrivateKey;

+ 18 - 0
Renci.SshClient/Renci.SshNet/Security/Cryptography/RSADigitalSignature.cs

@@ -7,17 +7,30 @@ using Renci.SshNet.Common;
 
 namespace Renci.SshNet.Security.Cryptography
 {
+    /// <summary>
+    /// Implements RSAdigital signature algorithm.
+    /// </summary>
     public class RSADigitalSignature : DigitalSignature
     {
         private HashAlgorithm _hash;
         private RSACipher _cipher;
 
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RSADigitalSignature"/> class.
+        /// </summary>
+        /// <param name="key">The key.</param>
         public RSADigitalSignature(RSAPublicKey key)
         {
             this._hash = new SHA1Hash();
             this._cipher = new RSACipher(this._hash, key);
         }
 
+        /// <summary>
+        /// Verifies the signature.
+        /// </summary>
+        /// <param name="input">The input.</param>
+        /// <param name="signature">The signature.</param>
+        /// <returns></returns>
         public override bool VerifySignature(byte[] input, byte[] signature)
         {
             var sig = this._cipher.Transform(signature);
@@ -49,6 +62,11 @@ namespace Renci.SshNet.Security.Cryptography
             return true;
         }
 
+        /// <summary>
+        /// Creates the signature.
+        /// </summary>
+        /// <param name="input">The input.</param>
+        /// <returns></returns>
         public override byte[] CreateSignature(byte[] input)
         {
             //  Calculate hash value

+ 379 - 376
Renci.SshClient/Renci.SshNet/Security/Cryptography/SHA256Hash.cs

@@ -6,381 +6,384 @@ using System.Security.Cryptography;
 
 namespace Renci.SshNet.Security.Cryptography
 {
-    public class SHA256Hash : HashAlgorithm
-    {
-        private const int DIGEST_SIZE = 32;
-
-        private uint H1, H2, H3, H4, H5, H6, H7, H8;
-
-        private uint[] X = new uint[64];
-
-        private int _offset;
-
-        private byte[] _buffer;
-
-        private int _bufferOffset;
-
-        private long _byteCount;
-
-        /// <summary>
-        /// Gets the size, in bits, of the computed hash code.
-        /// </summary>
-        /// <returns>The size, in bits, of the computed hash code.</returns>
-        public override int HashSize
-        {
-            get
-            {
-                return DIGEST_SIZE * 8;
-            }
-        }
-
-        /// <summary>
-        /// Gets the input block size.
-        /// </summary>
-        /// <returns>The input block size.</returns>
-        public override int InputBlockSize
-        {
-            get
-            {
-                return 64;
-            }
-        }
-
-        /// <summary>
-        /// Gets the output block size.
-        /// </summary>
-        /// <returns>The output block size.</returns>
-        public override int OutputBlockSize
-        {
-            get
-            {
-                return 64;
-            }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether the current transform can be reused.
-        /// </summary>
-        /// <returns>Always true.</returns>
-        public override bool CanReuseTransform
-        {
-            get
-            {
-                return true;
-            }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether multiple blocks can be transformed.
-        /// </summary>
-        /// <returns>true if multiple blocks can be transformed; otherwise, false.</returns>
-        public override bool CanTransformMultipleBlocks
-        {
-            get
-            {
-                return true;
-            }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="SHA1"/> class.
-        /// </summary>
-        public SHA256Hash()
-        {
-            this._buffer = new byte[4];
-            this.Initialize();
-        }
-
-        /// <summary>
-        /// Routes data written to the object into the hash algorithm for computing the hash.
-        /// </summary>
-        /// <param name="array">The input to compute the hash code for.</param>
-        /// <param name="ibStart">The offset into the byte array from which to begin using data.</param>
-        /// <param name="cbSize">The number of bytes in the byte array to use as data.</param>
-        protected override void HashCore(byte[] array, int ibStart, int cbSize)
-        {
-            //  Fill the current word
-            while ((this._bufferOffset != 0) && (cbSize > 0))
-            {
-                this.Update(array[ibStart]);
-                ibStart++;
-                cbSize--;
-            }
-
-            //  Process whole words.
-            while (cbSize > this._buffer.Length)
-            {
-                this.ProcessWord(array, ibStart);
-
-                ibStart += this._buffer.Length;
-                cbSize -= this._buffer.Length;
-                this._byteCount += this._buffer.Length;
-            }
-
-            //  Load in the remainder.
-            while (cbSize > 0)
-            {
-                this.Update(array[ibStart]);
-
-                ibStart++;
-                cbSize--;
-            }
-        }
-
-        /// <summary>
-        /// Finalizes the hash computation after the last data is processed by the cryptographic stream object.
-        /// </summary>
-        /// <returns>
-        /// The computed hash code.
-        /// </returns>
-        protected override byte[] HashFinal()
-        {
-            var output = new byte[DIGEST_SIZE];
-            long bitLength = (this._byteCount << 3);
-
-            //
-            // add the pad bytes.
-            //
-            this.Update((byte)128);
-
-            while (this._bufferOffset != 0)
-                this.Update((byte)0);
-
-            if (this._offset > 14)
-            {
-                this.ProcessBlock();
-            }
-
-            X[14] = (uint)((ulong)bitLength >> 32);
-            X[15] = (uint)((ulong)bitLength);
-
-
-            this.ProcessBlock();
-
-            UInt32_To_BE((uint)H1, output, 0);
-            UInt32_To_BE((uint)H2, output, 0 + 4);
-            UInt32_To_BE((uint)H3, output, 0 + 8);
-            UInt32_To_BE((uint)H4, output, 0 + 12);
-            UInt32_To_BE((uint)H5, output, 0 + 16);
-            UInt32_To_BE((uint)H6, output, 0 + 20);
-            UInt32_To_BE((uint)H7, output, 0 + 24);
-            UInt32_To_BE((uint)H8, output, 0 + 28);
-
-            this.Initialize();
-
-            return output;
-        }
-
-        /// <summary>
-        /// Initializes an implementation of the <see cref="T:System.Security.Cryptography.HashAlgorithm"/> class.
-        /// </summary>
-        public override void Initialize()
-        {
-            //this.Reset();
-            this._byteCount = 0;
-            this._bufferOffset = 0;
-            Array.Clear(this._buffer, 0, this._buffer.Length);
-
-            H1 = 0x6a09e667;
-            H2 = 0xbb67ae85;
-            H3 = 0x3c6ef372;
-            H4 = 0xa54ff53a;
-            H5 = 0x510e527f;
-            H6 = 0x9b05688c;
-            H7 = 0x1f83d9ab;
-            H8 = 0x5be0cd19;
-
-            this._offset = 0;
-            Array.Clear(X, 0, X.Length);
-        }
-
-        private void Update(byte input)
-        {
-            this._buffer[this._bufferOffset++] = input;
-
-            if (this._bufferOffset == this._buffer.Length)
-            {
-                this.ProcessWord(this._buffer, 0);
-                this._bufferOffset = 0;
-            }
-
-            this._byteCount++;
-        }
-
-        private static uint BE_To_UInt32(byte[] bs, int off)
-        {
-            uint n = (uint)bs[off] << 24;
-            n |= (uint)bs[++off] << 16;
-            n |= (uint)bs[++off] << 8;
-            n |= (uint)bs[++off];
-            return n;
-        }
-
-        private static void UInt32_To_BE(uint n, byte[] bs, int off)
-        {
-            bs[off] = (byte)(n >> 24);
-            bs[++off] = (byte)(n >> 16);
-            bs[++off] = (byte)(n >> 8);
-            bs[++off] = (byte)(n);
-        }
-
-        private void ProcessWord(byte[] input, int inOff)
-        {
-            X[this._offset] = BE_To_UInt32(input, inOff);
-
-            if (++this._offset == 16)
-            {
-                ProcessBlock();
-            }
-        }
-
-        private void ProcessLength(long bitLength)
-        {
-            if (this._offset > 14)
-            {
-                ProcessBlock();
-            }
-
-            X[14] = (uint)((ulong)bitLength >> 32);
-            X[15] = (uint)((ulong)bitLength);
-        }
-
-        private void ProcessBlock()
-        {
-            //
-            // expand 16 word block into 64 word blocks.
-            //
-            for (int ti = 16; ti <= 63; ti++)
-            {
-                X[ti] = Theta1(X[ti - 2]) + X[ti - 7] + Theta0(X[ti - 15]) + X[ti - 16];
-            }
-
-            //
-            // set up working variables.
-            //
-            uint a = H1;
-            uint b = H2;
-            uint c = H3;
-            uint d = H4;
-            uint e = H5;
-            uint f = H6;
-            uint g = H7;
-            uint h = H8;
-
-            int t = 0;
-            for (int i = 0; i < 8; ++i)
-            {
-                // t = 8 * i
-                h += Sum1Ch(e, f, g) + K[t] + X[t];
-                d += h;
-                h += Sum0Maj(a, b, c);
-                ++t;
-
-                // t = 8 * i + 1
-                g += Sum1Ch(d, e, f) + K[t] + X[t];
-                c += g;
-                g += Sum0Maj(h, a, b);
-                ++t;
-
-                // t = 8 * i + 2
-                f += Sum1Ch(c, d, e) + K[t] + X[t];
-                b += f;
-                f += Sum0Maj(g, h, a);
-                ++t;
-
-                // t = 8 * i + 3
-                e += Sum1Ch(b, c, d) + K[t] + X[t];
-                a += e;
-                e += Sum0Maj(f, g, h);
-                ++t;
-
-                // t = 8 * i + 4
-                d += Sum1Ch(a, b, c) + K[t] + X[t];
-                h += d;
-                d += Sum0Maj(e, f, g);
-                ++t;
-
-                // t = 8 * i + 5
-                c += Sum1Ch(h, a, b) + K[t] + X[t];
-                g += c;
-                c += Sum0Maj(d, e, f);
-                ++t;
-
-                // t = 8 * i + 6
-                b += Sum1Ch(g, h, a) + K[t] + X[t];
-                f += b;
-                b += Sum0Maj(c, d, e);
-                ++t;
-
-                // t = 8 * i + 7
-                a += Sum1Ch(f, g, h) + K[t] + X[t];
-                e += a;
-                a += Sum0Maj(b, c, d);
-                ++t;
-            }
-
-            H1 += a;
-            H2 += b;
-            H3 += c;
-            H4 += d;
-            H5 += e;
-            H6 += f;
-            H7 += g;
-            H8 += h;
-
-            //
-            // reset the offset and clean out the word buffer.
-            //
-            this._offset = 0;
-            Array.Clear(X, 0, 16);
-        }
-
-        private static uint Sum1Ch(uint x, uint y, uint z)
-        {
-            //			return Sum1(x) + Ch(x, y, z);
-            return (((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7)))
-                + ((x & y) ^ ((~x) & z));
-        }
-
-        private static uint Sum0Maj(uint x, uint y, uint z)
-        {
-            //			return Sum0(x) + Maj(x, y, z);
-            return (((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10)))
-                + ((x & y) ^ (x & z) ^ (y & z));
-        }
-
-        private static uint Theta0(uint x)
-        {
-            return ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ (x >> 3);
-        }
-
-        private static uint Theta1(uint x)
-        {
-            return ((x >> 17) | (x << 15)) ^ ((x >> 19) | (x << 13)) ^ (x >> 10);
-        }
-
-        /* SHA-256 Constants
-        * (represent the first 32 bits of the fractional parts of the
-        * cube roots of the first sixty-four prime numbers)
-        */
-        private static readonly uint[] K = {
-            0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+	/// <summary>
+	/// SHA256 algorithm implementation.
+	/// </summary>
+	public class SHA256Hash : HashAlgorithm
+	{
+		private const int DIGEST_SIZE = 32;
+
+		private uint H1, H2, H3, H4, H5, H6, H7, H8;
+
+		private uint[] X = new uint[64];
+
+		private int _offset;
+
+		private byte[] _buffer;
+
+		private int _bufferOffset;
+
+		private long _byteCount;
+
+		/// <summary>
+		/// Gets the size, in bits, of the computed hash code.
+		/// </summary>
+		/// <returns>The size, in bits, of the computed hash code.</returns>
+		public override int HashSize
+		{
+			get
+			{
+				return DIGEST_SIZE * 8;
+			}
+		}
+
+		/// <summary>
+		/// Gets the input block size.
+		/// </summary>
+		/// <returns>The input block size.</returns>
+		public override int InputBlockSize
+		{
+			get
+			{
+				return 64;
+			}
+		}
+
+		/// <summary>
+		/// Gets the output block size.
+		/// </summary>
+		/// <returns>The output block size.</returns>
+		public override int OutputBlockSize
+		{
+			get
+			{
+				return 64;
+			}
+		}
+
+		/// <summary>
+		/// Gets a value indicating whether the current transform can be reused.
+		/// </summary>
+		/// <returns>Always true.</returns>
+		public override bool CanReuseTransform
+		{
+			get
+			{
+				return true;
+			}
+		}
+
+		/// <summary>
+		/// Gets a value indicating whether multiple blocks can be transformed.
+		/// </summary>
+		/// <returns>true if multiple blocks can be transformed; otherwise, false.</returns>
+		public override bool CanTransformMultipleBlocks
+		{
+			get
+			{
+				return true;
+			}
+		}
+
+		/// <summary>
+		/// Initializes a new instance of the <see cref="SHA1"/> class.
+		/// </summary>
+		public SHA256Hash()
+		{
+			this._buffer = new byte[4];
+			this.Initialize();
+		}
+
+		/// <summary>
+		/// Routes data written to the object into the hash algorithm for computing the hash.
+		/// </summary>
+		/// <param name="array">The input to compute the hash code for.</param>
+		/// <param name="ibStart">The offset into the byte array from which to begin using data.</param>
+		/// <param name="cbSize">The number of bytes in the byte array to use as data.</param>
+		protected override void HashCore(byte[] array, int ibStart, int cbSize)
+		{
+			//  Fill the current word
+			while ((this._bufferOffset != 0) && (cbSize > 0))
+			{
+				this.Update(array[ibStart]);
+				ibStart++;
+				cbSize--;
+			}
+
+			//  Process whole words.
+			while (cbSize > this._buffer.Length)
+			{
+				this.ProcessWord(array, ibStart);
+
+				ibStart += this._buffer.Length;
+				cbSize -= this._buffer.Length;
+				this._byteCount += this._buffer.Length;
+			}
+
+			//  Load in the remainder.
+			while (cbSize > 0)
+			{
+				this.Update(array[ibStart]);
+
+				ibStart++;
+				cbSize--;
+			}
+		}
+
+		/// <summary>
+		/// Finalizes the hash computation after the last data is processed by the cryptographic stream object.
+		/// </summary>
+		/// <returns>
+		/// The computed hash code.
+		/// </returns>
+		protected override byte[] HashFinal()
+		{
+			var output = new byte[DIGEST_SIZE];
+			long bitLength = (this._byteCount << 3);
+
+			//
+			// add the pad bytes.
+			//
+			this.Update((byte)128);
+
+			while (this._bufferOffset != 0)
+				this.Update((byte)0);
+
+			if (this._offset > 14)
+			{
+				this.ProcessBlock();
+			}
+
+			X[14] = (uint)((ulong)bitLength >> 32);
+			X[15] = (uint)((ulong)bitLength);
+
+
+			this.ProcessBlock();
+
+			UInt32_To_BE((uint)H1, output, 0);
+			UInt32_To_BE((uint)H2, output, 0 + 4);
+			UInt32_To_BE((uint)H3, output, 0 + 8);
+			UInt32_To_BE((uint)H4, output, 0 + 12);
+			UInt32_To_BE((uint)H5, output, 0 + 16);
+			UInt32_To_BE((uint)H6, output, 0 + 20);
+			UInt32_To_BE((uint)H7, output, 0 + 24);
+			UInt32_To_BE((uint)H8, output, 0 + 28);
+
+			this.Initialize();
+
+			return output;
+		}
+
+		/// <summary>
+		/// Initializes an implementation of the <see cref="T:System.Security.Cryptography.HashAlgorithm"/> class.
+		/// </summary>
+		public override void Initialize()
+		{
+			//this.Reset();
+			this._byteCount = 0;
+			this._bufferOffset = 0;
+			Array.Clear(this._buffer, 0, this._buffer.Length);
+
+			H1 = 0x6a09e667;
+			H2 = 0xbb67ae85;
+			H3 = 0x3c6ef372;
+			H4 = 0xa54ff53a;
+			H5 = 0x510e527f;
+			H6 = 0x9b05688c;
+			H7 = 0x1f83d9ab;
+			H8 = 0x5be0cd19;
+
+			this._offset = 0;
+			Array.Clear(X, 0, X.Length);
+		}
+
+		private void Update(byte input)
+		{
+			this._buffer[this._bufferOffset++] = input;
+
+			if (this._bufferOffset == this._buffer.Length)
+			{
+				this.ProcessWord(this._buffer, 0);
+				this._bufferOffset = 0;
+			}
+
+			this._byteCount++;
+		}
+
+		private static uint BE_To_UInt32(byte[] bs, int off)
+		{
+			uint n = (uint)bs[off] << 24;
+			n |= (uint)bs[++off] << 16;
+			n |= (uint)bs[++off] << 8;
+			n |= (uint)bs[++off];
+			return n;
+		}
+
+		private static void UInt32_To_BE(uint n, byte[] bs, int off)
+		{
+			bs[off] = (byte)(n >> 24);
+			bs[++off] = (byte)(n >> 16);
+			bs[++off] = (byte)(n >> 8);
+			bs[++off] = (byte)(n);
+		}
+
+		private void ProcessWord(byte[] input, int inOff)
+		{
+			X[this._offset] = BE_To_UInt32(input, inOff);
+
+			if (++this._offset == 16)
+			{
+				ProcessBlock();
+			}
+		}
+
+		private void ProcessLength(long bitLength)
+		{
+			if (this._offset > 14)
+			{
+				ProcessBlock();
+			}
+
+			X[14] = (uint)((ulong)bitLength >> 32);
+			X[15] = (uint)((ulong)bitLength);
+		}
+
+		private void ProcessBlock()
+		{
+			//
+			// expand 16 word block into 64 word blocks.
+			//
+			for (int ti = 16; ti <= 63; ti++)
+			{
+				X[ti] = Theta1(X[ti - 2]) + X[ti - 7] + Theta0(X[ti - 15]) + X[ti - 16];
+			}
+
+			//
+			// set up working variables.
+			//
+			uint a = H1;
+			uint b = H2;
+			uint c = H3;
+			uint d = H4;
+			uint e = H5;
+			uint f = H6;
+			uint g = H7;
+			uint h = H8;
+
+			int t = 0;
+			for (int i = 0; i < 8; ++i)
+			{
+				// t = 8 * i
+				h += Sum1Ch(e, f, g) + K[t] + X[t];
+				d += h;
+				h += Sum0Maj(a, b, c);
+				++t;
+
+				// t = 8 * i + 1
+				g += Sum1Ch(d, e, f) + K[t] + X[t];
+				c += g;
+				g += Sum0Maj(h, a, b);
+				++t;
+
+				// t = 8 * i + 2
+				f += Sum1Ch(c, d, e) + K[t] + X[t];
+				b += f;
+				f += Sum0Maj(g, h, a);
+				++t;
+
+				// t = 8 * i + 3
+				e += Sum1Ch(b, c, d) + K[t] + X[t];
+				a += e;
+				e += Sum0Maj(f, g, h);
+				++t;
+
+				// t = 8 * i + 4
+				d += Sum1Ch(a, b, c) + K[t] + X[t];
+				h += d;
+				d += Sum0Maj(e, f, g);
+				++t;
+
+				// t = 8 * i + 5
+				c += Sum1Ch(h, a, b) + K[t] + X[t];
+				g += c;
+				c += Sum0Maj(d, e, f);
+				++t;
+
+				// t = 8 * i + 6
+				b += Sum1Ch(g, h, a) + K[t] + X[t];
+				f += b;
+				b += Sum0Maj(c, d, e);
+				++t;
+
+				// t = 8 * i + 7
+				a += Sum1Ch(f, g, h) + K[t] + X[t];
+				e += a;
+				a += Sum0Maj(b, c, d);
+				++t;
+			}
+
+			H1 += a;
+			H2 += b;
+			H3 += c;
+			H4 += d;
+			H5 += e;
+			H6 += f;
+			H7 += g;
+			H8 += h;
+
+			//
+			// reset the offset and clean out the word buffer.
+			//
+			this._offset = 0;
+			Array.Clear(X, 0, 16);
+		}
+
+		private static uint Sum1Ch(uint x, uint y, uint z)
+		{
+			//			return Sum1(x) + Ch(x, y, z);
+			return (((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7)))
+				+ ((x & y) ^ ((~x) & z));
+		}
+
+		private static uint Sum0Maj(uint x, uint y, uint z)
+		{
+			//			return Sum0(x) + Maj(x, y, z);
+			return (((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10)))
+				+ ((x & y) ^ (x & z) ^ (y & z));
+		}
+
+		private static uint Theta0(uint x)
+		{
+			return ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ (x >> 3);
+		}
+
+		private static uint Theta1(uint x)
+		{
+			return ((x >> 17) | (x << 15)) ^ ((x >> 19) | (x << 13)) ^ (x >> 10);
+		}
+
+		/* SHA-256 Constants
+		* (represent the first 32 bits of the fractional parts of the
+		* cube roots of the first sixty-four prime numbers)
+		*/
+		private static readonly uint[] K = {
+			0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
 			0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
-            0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
-            0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
-            0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
-            0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
-            0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
-            0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
-            0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
-            0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
-            0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
-            0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
-            0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
-            0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
-            0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
-            0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
-        };
-
-    }
+			0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+			0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+			0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+			0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+			0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+			0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+			0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+			0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+			0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+			0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+			0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+			0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+			0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+			0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+		};
+
+	}
 }