瀏覽代碼

Add SHA1 algorithm
Add RSA Private key algorithm
Adding some Silverlight specific #if...#endif

olegkap_cp 14 年之前
父節點
當前提交
40b36edaf1

+ 73 - 2
Renci.SshClient/Renci.SshNet/Common/BigInteger.cs

@@ -74,11 +74,30 @@ namespace Renci.SshNet.Common
 
         private static readonly uint[] _zero = new uint[1];
         private static readonly uint[] _one = new uint[1] { 1 };
-        
+
         //LSB on [0]
         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>
@@ -2271,8 +2290,10 @@ namespace Renci.SshNet.Common
                     result = result * value;
                     result = result % modulus;
                 }
+
                 if (exponent.IsOne)
                     break;
+
                 value = value * value;
                 value = value % modulus;
                 exponent >>= 1;
@@ -2280,6 +2301,55 @@ namespace Renci.SshNet.Common
             return result;
         }
 
+        /// <summary>
+        /// Mods the inverse.
+        /// </summary>
+        /// <param name="bi">The bi.</param>
+        /// <param name="modulus">The modulus.</param>
+        /// <returns></returns>
+        public static BigInteger ModInverse(BigInteger bi, BigInteger modulus)
+        {
+            BigInteger a = modulus, b = bi % modulus;
+            BigInteger p0 = 0, p1 = 1;
+
+            while (!b.IsZero)
+            {
+                if (b.IsOne)
+                    return p1;
+
+                p0 += (a / b) * p1;
+                a %= b;
+
+                if (a.IsZero)
+                    break;
+
+                if (a.IsOne)
+                    return modulus - p0;
+
+                p1 += (b / a) * p0;
+                b %= a;
+
+            }
+            return 0;
+        }
+
+        /// <summary>
+        /// Returns positive remainder that results from division with two specified <see cref="BigInteger"/> values.
+        /// </summary>
+        /// <param name="dividend">The value to be divided.</param>
+        /// <param name="divisor">The value to divide by.</param>
+        /// <returns>
+        /// Positive remainder that results from the division.
+        /// </returns>
+        public static BigInteger PositiveMod(BigInteger dividend, BigInteger divisor)
+        {
+            var result = dividend % divisor;
+            if (result < 0)
+                result += divisor;
+
+            return result;
+        }
+
         /// <summary>
         /// Returns the product of two System.Numerics.BigInteger values.
         /// </summary>
@@ -2836,6 +2906,8 @@ namespace Renci.SshNet.Common
             var baseNumber = 10;
             switch (style)
             {
+                case NumberStyles.None:
+                    break;
                 case NumberStyles.HexNumber:
                 case NumberStyles.AllowHexSpecifier:
                     baseNumber = 16;
@@ -2853,7 +2925,6 @@ namespace Renci.SshNet.Common
                 case NumberStyles.Currency:
                 case NumberStyles.Float:
                 case NumberStyles.Integer:
-                case NumberStyles.None:
                 case NumberStyles.Number:
                 default:
                     throw new NotSupportedException(string.Format("Style '{0}' is not supported.", style));

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

@@ -167,10 +167,17 @@ namespace Renci.SshNet
             return new byte[] { (byte)(value >> 56), (byte)(value >> 48), (byte)(value >> 40), (byte)(value >> 32), (byte)(value >> 24), (byte)(value >> 16), (byte)(value >> 8), (byte)(value & 0xFF) };
         }
 
-        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);
+#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);
+
         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 | RegexOptions.Compiled);
 
+#endif
+
         internal static bool IsValidHost(this string value)
         {
             if (value == null)

+ 4 - 0
Renci.SshClient/Renci.SshNet/PrivateKeyFile.cs

@@ -17,7 +17,11 @@ namespace Renci.SshNet
     /// </summary>
     public class PrivateKeyFile
     {
+#if SILVERLIGHT
+        private static Regex _privateKeyRegex = new Regex(@"^-----BEGIN (?<keyName>\w+) PRIVATE KEY-----\r?\n(Proc-Type: 4,ENCRYPTED\r?\nDEK-Info: (?<cipherName>[A-Z0-9-]+),(?<salt>[A-F0-9]{16})\r?\n\r?\n)?(?<data>([a-zA-Z0-9/+=]{1,64}\r?\n)+)-----END \k<keyName> PRIVATE KEY-----.*", RegexOptions.Multiline);
+#else
         private static Regex _privateKeyRegex = new Regex(@"^-----BEGIN (?<keyName>\w+) PRIVATE KEY-----\r?\n(Proc-Type: 4,ENCRYPTED\r?\nDEK-Info: (?<cipherName>[A-Z0-9-]+),(?<salt>[A-F0-9]{16})\r?\n\r?\n)?(?<data>([a-zA-Z0-9/+=]{1,64}\r?\n)+)-----END \k<keyName> PRIVATE KEY-----.*", RegexOptions.Compiled | RegexOptions.Multiline);
+#endif
 
         private CryptoPrivateKey _key;
 

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

@@ -130,10 +130,35 @@
     <Compile Include="Security\CipherTripleDesCbc.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Security\Cryptography\AsymmetricCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\Cryptography\DigitalSignature.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\Cryptography\DSACipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\Cryptography\DSAParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="Security\Cryptography\HMAC.cs">
       <SubType>Code</SubType>
     </Compile>
-    <Compile Include="Security\Cryptography\MD5.cs">
+    <Compile Include="Security\Cryptography\MD5Hash.cs" />
+    <Compile Include="Security\Cryptography\RSACipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\Cryptography\RSADigitalSignature.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\Cryptography\RSAPrivateKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\Cryptography\RSAPublicKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\Cryptography\SHA1Hash.cs">
       <SubType>Code</SubType>
     </Compile>
     <Compile Include="Security\CryptoKey.cs">

+ 9 - 7
Renci.SshClient/Renci.SshNet/Security/CryptoPrivateKeyDss.cs

@@ -4,6 +4,7 @@ using System.IO;
 using System.Linq;
 using System.Security.Cryptography;
 using Renci.SshNet.Common;
+using Renci.SshNet.Security.Cryptography;
 
 namespace Renci.SshNet.Security
 {
@@ -102,20 +103,21 @@ namespace Renci.SshNet.Security
         public override byte[] GetSignature(IEnumerable<byte> key)
         {
             var data = key.ToArray();
+            //using (var sha1 = new Renci.SshNet.Security.Cryptography.SHA1Hash())
             using (var sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider())
             {
-                DSAParameters dsaKeyInfo = new DSAParameters();
-
                 using (var cs = new System.Security.Cryptography.CryptoStream(System.IO.Stream.Null, sha1, System.Security.Cryptography.CryptoStreamMode.Write))
                 {
-                    dsaKeyInfo.X = this._privateKey.TrimLeadingZero().ToArray();
-                    dsaKeyInfo.P = this._p.TrimLeadingZero().ToArray();
-                    dsaKeyInfo.Q = this._q.TrimLeadingZero().ToArray();
-                    dsaKeyInfo.G = this._g.TrimLeadingZero().ToArray();
-
                     cs.Write(data, 0, data.Length);
                 }
 
+                var dsaKeyInfo = new System.Security.Cryptography.DSAParameters();
+
+                dsaKeyInfo.X = this._privateKey.TrimLeadingZero().ToArray();
+                dsaKeyInfo.P = this._p.TrimLeadingZero().ToArray();
+                dsaKeyInfo.Q = this._q.TrimLeadingZero().ToArray();
+                dsaKeyInfo.G = this._g.TrimLeadingZero().ToArray();
+
                 using (var DSA = new System.Security.Cryptography.DSACryptoServiceProvider())
                 {
                     DSA.ImportParameters(dsaKeyInfo);

+ 7 - 34
Renci.SshClient/Renci.SshNet/Security/CryptoPrivateKeyRsa.cs

@@ -2,8 +2,8 @@
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
-using System.Security.Cryptography;
 using Renci.SshNet.Common;
+using Renci.SshNet.Security.Cryptography;
 
 namespace Renci.SshNet.Security
 {
@@ -113,40 +113,13 @@ namespace Renci.SshNet.Security
         /// <returns></returns>
         public override byte[] GetSignature(IEnumerable<byte> key)
         {
-            var data = key.ToArray();
-            using (var sha1 = new System.Security.Cryptography.SHA1CryptoServiceProvider())
-            {
-                RSAParameters rsaKeyInfo = new RSAParameters();
-
-                using (var cs = new System.Security.Cryptography.CryptoStream(System.IO.Stream.Null, sha1, System.Security.Cryptography.CryptoStreamMode.Write))
-                {
-                    rsaKeyInfo.Exponent = this._exponent.TrimLeadingZero().ToArray();
-                    rsaKeyInfo.D = this._dValue.TrimLeadingZero().ToArray();
-                    rsaKeyInfo.Modulus = this._modulus.TrimLeadingZero().ToArray();
-                    rsaKeyInfo.P = this._pValue.TrimLeadingZero().ToArray();
-                    rsaKeyInfo.Q = this._qValue.TrimLeadingZero().ToArray();
-                    rsaKeyInfo.DP = this._dpValue.TrimLeadingZero().ToArray();
-                    rsaKeyInfo.DQ = this._dqValue.TrimLeadingZero().ToArray();
-                    rsaKeyInfo.InverseQ = this._inverseQ.TrimLeadingZero().ToArray();
-
-                    cs.Write(data, 0, data.Length);
-                }
-
-                using (var RSA = new System.Security.Cryptography.RSACryptoServiceProvider())
-                {
-                    RSA.ImportParameters(rsaKeyInfo);
-                    var RSAFormatter = new RSAPKCS1SignatureFormatter(RSA);
-                    RSAFormatter.SetHashAlgorithm("SHA1");
-
-                    var signature = RSAFormatter.CreateSignature(sha1);
+            var signature = new RSADigitalSignature(new RSAPrivateKey(this._exponent, this._modulus, this._dValue, this._dpValue, this._qValue, this._dqValue, this._pValue, this._inverseQ));
 
-                    return new SignatureKeyData
-                    {
-                        AlgorithmName = this.Name,
-                        Signature = signature,
-                    }.GetBytes().ToArray();
-                }
-            }
+            return new SignatureKeyData
+            {
+                AlgorithmName = this.Name,
+                Signature = signature.CreateSignature(key.ToArray()),
+            }.GetBytes().ToArray();
         }
 
         /// <summary>

+ 29 - 46
Renci.SshClient/Renci.SshNet/Security/CryptoPublicKeyRsa.cs

@@ -4,6 +4,7 @@ using System.IO;
 using System.Linq;
 using System.Security.Cryptography;
 using Renci.SshNet.Common;
+using Renci.SshNet.Security.Cryptography;
 
 namespace Renci.SshNet.Security
 {
@@ -84,54 +85,36 @@ namespace Renci.SshNet.Security
         /// </returns>
         public override bool VerifySignature(IEnumerable<byte> hash, IEnumerable<byte> signature)
         {
-            using (var sha1 = new SHA1CryptoServiceProvider())
-            {
-                using (var cs = new CryptoStream(System.IO.Stream.Null, sha1, CryptoStreamMode.Write))
-                {
-                    var data = hash.ToArray();
-                    cs.Write(data, 0, data.Length);
-                }
+            long i = 0;
+            long j = 0;
+            byte[] tmp;
 
-                using (var rsa = new RSACryptoServiceProvider())
-                {
-                    rsa.ImportParameters(new RSAParameters
-                    {
-                        Exponent = this._exponent.TrimLeadingZero().ToArray(),
-                        Modulus = this._modulus.TrimLeadingZero().ToArray(),
-                    });
-
-                    var rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa);
-                    rsaDeformatter.SetHashAlgorithm("SHA1");
-
-                    long i = 0;
-                    long j = 0;
-                    byte[] tmp;
-
-                    var sig = signature.ToArray();
-                    if (sig[0] == 0 && sig[1] == 0 && sig[2] == 0)
-                    {
-                        long i1 = (sig[i++] << 24) & 0xff000000;
-                        long i2 = (sig[i++] << 16) & 0x00ff0000;
-                        long i3 = (sig[i++] << 8) & 0x0000ff00;
-                        long i4 = (sig[i++]) & 0x000000ff;
-                        j = i1 | i2 | i3 | i4;
-
-                        i += j;
-
-                        i1 = (sig[i++] << 24) & 0xff000000;
-                        i2 = (sig[i++] << 16) & 0x00ff0000;
-                        i3 = (sig[i++] << 8) & 0x0000ff00;
-                        i4 = (sig[i++]) & 0x000000ff;
-                        j = i1 | i2 | i3 | i4;
-
-                        tmp = new byte[j];
-                        Array.Copy(sig, (int)i, tmp, 0, (int)j);
-                        sig = tmp;
-                    }
-
-                    return rsaDeformatter.VerifySignature(sha1, sig);
-                }
+            var sig = signature.ToArray();
+            if (sig[0] == 0 && sig[1] == 0 && sig[2] == 0)
+            {
+                long i1 = (sig[i++] << 24) & 0xff000000;
+                long i2 = (sig[i++] << 16) & 0x00ff0000;
+                long i3 = (sig[i++] << 8) & 0x0000ff00;
+                long i4 = (sig[i++]) & 0x000000ff;
+                j = i1 | i2 | i3 | i4;
+
+                i += j;
+
+                i1 = (sig[i++] << 24) & 0xff000000;
+                i2 = (sig[i++] << 16) & 0x00ff0000;
+                i3 = (sig[i++] << 8) & 0x0000ff00;
+                i4 = (sig[i++]) & 0x000000ff;
+                j = i1 | i2 | i3 | i4;
+
+                tmp = new byte[j];
+                Array.Copy(sig, (int)i, tmp, 0, (int)j);
+                sig = tmp;
             }
+
+            var sig1 = new RSADigitalSignature(new RSAPublicKey(this._exponent, this._modulus));
+
+            return sig1.VerifySignature(hash.ToArray(), sig);
+
         }
 
         /// <summary>

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

@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+    public abstract class AsymmetricCipher
+    {
+        public abstract byte[] Transform(byte[] input);
+
+        public abstract BigInteger Transform(BigInteger input);
+    }
+}

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

@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Security.Cryptography;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+    public abstract class DigitalSignature
+    {
+        public abstract bool VerifySignature(byte[] input, byte[] signature);
+
+        public abstract byte[] CreateSignature(byte[] input);
+    }
+}

+ 3 - 3
Renci.SshClient/Renci.SshNet/Security/Cryptography/MD5.cs → Renci.SshClient/Renci.SshNet/Security/Cryptography/MD5Hash.cs

@@ -9,7 +9,7 @@ namespace Renci.SshNet.Security.Cryptography
     /// <summary>
     /// MD5 algorithm implementation
     /// </summary>
-    public class MD5 : HashAlgorithm
+    public class MD5Hash : HashAlgorithm
     {
         private byte[] _buffer = new byte[4];
         private int _bufferOffset;
@@ -79,9 +79,9 @@ namespace Renci.SshNet.Security.Cryptography
         }
 
         /// <summary>
-        /// Initializes a new instance of the <see cref="MD5"/> class.
+        /// Initializes a new instance of the <see cref="MD5Hash"/> class.
         /// </summary>
-        public MD5()
+        public MD5Hash()
         {
             this.Initialize();
         }

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

@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Security.Cryptography;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+    public class RSACipher : AsymmetricCipher
+    {
+        private static RNGCryptoServiceProvider _randomizer = new System.Security.Cryptography.RNGCryptoServiceProvider();
+
+        private RSAPublicKey _key;
+
+        public RSACipher(HashAlgorithm hash, RSAPublicKey key)
+        {
+            this._key = key;
+        }
+
+        public override byte[] Transform(byte[] data)
+        {
+            var bytes = new List<byte>(data.Reverse());
+            bytes.Add(0);
+            return this.Transform(new BigInteger(bytes.ToArray())).ToByteArray().Reverse().ToArray();
+        }
+
+        public override BigInteger Transform(BigInteger input)
+        {
+            var privateKey = this._key as RSAPrivateKey;
+
+            if (privateKey != null)
+            {
+                BigInteger random = BigInteger.One;
+
+                var max = this._key.Modulus - 1;
+
+                while (random <= BigInteger.One || random >= max)
+                {
+                    var bytesArray = new byte[256];
+                    _randomizer.GetBytes(bytesArray);
+
+                    bytesArray[bytesArray.Length - 1] = (byte)(bytesArray[bytesArray.Length - 1] & 0x7F);   //  Ensure not a negative value
+                    random = new BigInteger(bytesArray.Reverse().ToArray());
+                }
+
+                BigInteger blindedInput = BigInteger.PositiveMod((BigInteger.ModPow(random, this._key.Exponent, this._key.Modulus) * input), this._key.Modulus);
+
+                // mP = ((input Mod p) ^ dP)) Mod p
+                var mP = BigInteger.ModPow((blindedInput % privateKey.P), privateKey.DP, privateKey.P);
+
+                // mQ = ((input Mod q) ^ dQ)) Mod q
+                var mQ = BigInteger.ModPow((blindedInput % privateKey.Q), privateKey.DQ, privateKey.Q);
+
+                var h = BigInteger.PositiveMod(((mP - mQ) * privateKey.InverseQ), privateKey.P);
+
+                var m = h * privateKey.Q + mQ;
+
+                BigInteger rInv = BigInteger.ModInverse(random, this._key.Modulus);
+
+                return BigInteger.PositiveMod((m * rInv), this._key.Modulus);
+            }
+            else
+            {
+                var value = BigInteger.ModPow(input, this._key.Exponent, this._key.Modulus);
+                return value;
+            }
+        }
+    }
+}

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

@@ -0,0 +1,97 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Security.Cryptography;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+    public class RSADigitalSignature : DigitalSignature
+    {
+        private HashAlgorithm _hash;
+        private RSACipher _cipher;
+
+        public RSADigitalSignature(RSAPublicKey key)
+        {
+            this._hash = new SHA1Hash();
+            this._cipher = new RSACipher(this._hash, key);
+        }
+
+        public override bool VerifySignature(byte[] input, byte[] signature)
+        {
+            var sig = this._cipher.Transform(signature);
+
+            //  TODO:   Ensure that only 1 or 2 types are supported
+            var position = 1;
+            while (position < sig.Length && sig[position] != 0)
+                position++;
+            position++;
+
+
+            var sig1 = new byte[sig.Length - position];
+
+            Array.Copy(sig, position, sig1, 0, sig1.Length);
+
+            var hashData = this._hash.ComputeHash(input);
+
+            var expected = DerEncode(hashData);
+
+            if (expected.Count != sig1.Length)
+                return false;
+
+            for (int i = 0; i < expected.Count; i++)
+            {
+                if (expected[i] != sig1[i])
+                    return false;
+            }
+
+            return true;
+        }
+
+        public override byte[] CreateSignature(byte[] input)
+        {
+            //  Calculate hash value
+            var hashData = this._hash.ComputeHash(input);
+
+            //  Calculate DER string
+
+            //  Resolve algorithm identifier
+            var dd = DerEncode(hashData);
+
+            //  Calculate signature
+            var rsaInputBlockSize = new byte[255];
+            rsaInputBlockSize[0] = 0x01;
+            for (int i = 1; i < rsaInputBlockSize.Length - dd.Count - 1; i++)
+            {
+                rsaInputBlockSize[i] = 0xFF;
+            }
+
+            Array.Copy(dd.ToArray(), 0, rsaInputBlockSize, rsaInputBlockSize.Length - dd.Count, dd.Count);
+
+            var input1 = new BigInteger(rsaInputBlockSize.Reverse().ToArray());
+
+            return this._cipher.Transform(input1).ToByteArray().Reverse().TrimLeadingZero().ToArray();
+        }
+
+        private static List<byte> DerEncode(byte[] hashData)
+        {
+            //  TODO:   Replace with algorithm code
+            var algorithm = new byte[] { 6, 5, 43, 14, 3, 2, 26 };
+            var algorithmParams = new byte[] { 5, 0 };
+
+            var dd = new List<byte>(algorithm);
+            dd.AddRange(algorithmParams);
+            dd.Insert(0, (byte)dd.Count);
+            dd.Insert(0, 48);
+
+            dd.Add(4);
+            dd.Add((byte)hashData.Length);
+            dd.AddRange(hashData);
+
+            dd.Insert(0, (byte)dd.Count);
+            dd.Insert(0, 48);
+            return dd;
+        }
+    }
+}

+ 79 - 0
Renci.SshClient/Renci.SshNet/Security/Cryptography/RSAPrivateKey.cs

@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+    /// <summary>
+    /// Represents the standard parameters for the Renci.SshNet.Security.Cryptography.RSACipher algorithm.
+    /// </summary>
+    public class RSAPrivateKey : RSAPublicKey
+    {
+        /// <summary>
+        /// Represents the D parameter for the Renci.SshNet.Security.Cryptography.RSACipher algorithm.
+        /// </summary>
+        public BigInteger D { get; private set; }
+
+        /// <summary>
+        /// Represents the DP parameter for the Renci.SshNet.Security.Cryptography.RSACipher algorithm.
+        /// </summary>
+        public BigInteger DP { get; private set; }
+
+        /// <summary>
+        /// Represents the DQ parameter for the Renci.SshNet.Security.Cryptography.RSACipher algorithm.
+        /// </summary>
+        public BigInteger DQ { get; private set; }
+
+        /// <summary>
+        /// Represents the InverseQ parameter for the Renci.SshNet.Security.Cryptography.RSACipher algorithm.
+        /// </summary>
+        public BigInteger InverseQ { get; private set; }
+
+        /// <summary>
+        /// Represents the P parameter for the Renci.SshNet.Security.Cryptography.RSACipher algorithm.
+        /// </summary>
+        public BigInteger P { get; private set; }
+
+        /// <summary>
+        /// Represents the Q parameter for the Renci.SshNet.Security.Cryptography.RSACipher algorithm.
+        /// </summary>
+        public BigInteger Q { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RSAPrivateKey"/> class.
+        /// </summary>
+        /// <param name="exponent">The exponent.</param>
+        /// <param name="modulus">The modulus.</param>
+        /// <param name="d">The d.</param>
+        /// <param name="dp">The dp.</param>
+        /// <param name="q">The q.</param>
+        /// <param name="dq">The dq.</param>
+        /// <param name="p">The p.</param>
+        /// <param name="inverseQ">The inverse Q.</param>
+        public RSAPrivateKey(byte[] exponent, byte[] modulus, byte[] d, byte[] dp, byte[] q, byte[] dq, byte[] p, byte[] inverseQ)
+            : base(exponent, modulus)
+        {
+            if (d == null)
+                throw new ArgumentNullException("d");
+            if (dp == null)
+                throw new ArgumentNullException("dp");
+            if (q == null)
+                throw new ArgumentNullException("q");
+            if (dq == null)
+                throw new ArgumentNullException("dq");
+            if (p == null)
+                throw new ArgumentNullException("p");
+            if (inverseQ == null)
+                throw new ArgumentNullException("inverseQ");
+
+            this.D = new BigInteger(d.Reverse().ToArray());
+            this.DP = new BigInteger(dp.Reverse().ToArray());
+            this.Q = new BigInteger(q.Reverse().ToArray());
+            this.DQ = new BigInteger(dq.Reverse().ToArray());
+            this.P = new BigInteger(p.Reverse().ToArray());
+            this.InverseQ = new BigInteger(inverseQ.Reverse().ToArray());
+        }
+    }
+}

+ 40 - 0
Renci.SshClient/Renci.SshNet/Security/Cryptography/RSAPublicKey.cs

@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+    /// <summary>
+    /// Represents the standard parameters for the Renci.SshNet.Security.Cryptography.RSACipher algorithm.
+    /// </summary>
+    public class RSAPublicKey
+    {
+        /// <summary>
+        /// Represents the Exponent parameter for the Renci.SshNet.Security.Cryptography.RSACipher algorithm.
+        /// </summary>
+        public BigInteger Exponent { get; private set; }
+
+        /// <summary>
+        /// Represents the Modulus parameter for the Renci.SshNet.Security.Cryptography.RSACipher algorithm.
+        /// </summary>
+        public BigInteger Modulus { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RSAPublicKey"/> class.
+        /// </summary>
+        /// <param name="exponent">The exponent.</param>
+        /// <param name="modulus">The modulus.</param>
+        public RSAPublicKey(byte[] exponent, byte[] modulus)
+        {
+            if (exponent == null)
+                throw new ArgumentNullException("exponent");
+            if (modulus == null)
+                throw new ArgumentNullException("modulus");
+
+            this.Exponent = new BigInteger(exponent.Reverse().ToArray());
+            this.Modulus = new BigInteger(modulus.Reverse().ToArray());
+        }
+    }
+}

+ 382 - 0
Renci.SshClient/Renci.SshNet/Security/Cryptography/SHA1Hash.cs

@@ -0,0 +1,382 @@
+using System.Security.Cryptography;
+using System;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+	/// <summary>
+	/// SHA1 algorithm implementation
+	/// </summary>
+	public class SHA1Hash : HashAlgorithm
+	{
+		private const int DIGEST_SIZE = 20;
+
+		private const uint Y1 = 0x5a827999;
+
+		private const uint Y2 = 0x6ed9eba1;
+
+		private const uint Y3 = 0x8f1bbcdc;
+
+		private const uint Y4 = 0xca62c1d6;
+
+		private uint H1, H2, H3, H4, H5;
+		
+		private uint[] _hashValue = new uint[80];
+		
+		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="SHA1Hash"/> class.
+		/// </summary>
+		public SHA1Hash()
+		{
+			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();
+			}
+
+			_hashValue[14] = (uint)((ulong)bitLength >> 32);
+			_hashValue[15] = (uint)((ulong)bitLength);
+
+
+			this.ProcessBlock();
+
+			UInt32_To__BE(H1, output, 0);
+			UInt32_To__BE(H2, output, 0 + 4);
+			UInt32_To__BE(H3, output, 0 + 8);
+			UInt32_To__BE(H4, output, 0 + 12);
+			UInt32_To__BE(H5, output, 0 + 16);
+
+            this.Initialize();
+
+			return output;
+		}
+
+		/// <summary>
+		/// Initializes an implementation of the <see cref="T:System.Security.Cryptography.HashAlgorithm"/> class.
+		/// </summary>
+		public override void Initialize()
+		{
+			this._byteCount = 0;
+			this._bufferOffset = 0;
+			Array.Clear(this._buffer, 0, this._buffer.Length);
+
+			H1 = 0x67452301;
+			H2 = 0xefcdab89;
+			H3 = 0x98badcfe;
+			H4 = 0x10325476;
+			H5 = 0xc3d2e1f0;
+
+			this._offset = 0;
+			Array.Clear(_hashValue, 0, _hashValue.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 void ProcessWord(byte[] input, int inOff)
+		{
+			_hashValue[this._offset] = BE_To__UInt32(input, inOff);
+
+			if (++this._offset == 16)
+			{
+				this.ProcessBlock();
+			}
+		}
+
+		private static uint F(uint u, uint v, uint w)
+		{
+			return (u & v) | (~u & w);
+		}
+
+		private static uint H(uint u, uint v, uint w)
+		{
+			return u ^ v ^ w;
+		}
+
+		private static uint G(uint u, uint v, uint w)
+		{
+			return (u & v) | (u & w) | (v & w);
+		}
+
+		private void ProcessBlock()
+		{
+			//
+			// expand 16 word block into 80 word block.
+			//
+			for (int i = 16; i < 80; i++)
+			{
+				uint t = _hashValue[i - 3] ^ _hashValue[i - 8] ^ _hashValue[i - 14] ^ _hashValue[i - 16];
+				_hashValue[i] = t << 1 | t >> 31;
+			}
+
+			//
+			// set up working variables.
+			//
+			uint A = H1;
+			uint B = H2;
+			uint C = H3;
+			uint D = H4;
+			uint E = H5;
+
+			//
+			// round 1
+			//
+			int idx = 0;
+
+			for (int j = 0; j < 4; j++)
+			{
+				// E = rotateLeft(A, 5) + F(B, C, D) + E + X[idx++] + Y1
+				// B = rotateLeft(B, 30)
+				E += (A << 5 | (A >> 27)) + F(B, C, D) + _hashValue[idx++] + Y1;
+				B = B << 30 | (B >> 2);
+
+				D += (E << 5 | (E >> 27)) + F(A, B, C) + _hashValue[idx++] + Y1;
+				A = A << 30 | (A >> 2);
+
+				C += (D << 5 | (D >> 27)) + F(E, A, B) + _hashValue[idx++] + Y1;
+				E = E << 30 | (E >> 2);
+
+				B += (C << 5 | (C >> 27)) + F(D, E, A) + _hashValue[idx++] + Y1;
+				D = D << 30 | (D >> 2);
+
+				A += (B << 5 | (B >> 27)) + F(C, D, E) + _hashValue[idx++] + Y1;
+				C = C << 30 | (C >> 2);
+			}
+
+			//
+			// round 2
+			//
+			for (int j = 0; j < 4; j++)
+			{
+				// E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y2
+				// B = rotateLeft(B, 30)
+				E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y2;
+				B = B << 30 | (B >> 2);
+
+				D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y2;
+				A = A << 30 | (A >> 2);
+
+				C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y2;
+				E = E << 30 | (E >> 2);
+
+				B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y2;
+				D = D << 30 | (D >> 2);
+
+				A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y2;
+				C = C << 30 | (C >> 2);
+			}
+
+			//
+			// round 3
+			//
+			for (int j = 0; j < 4; j++)
+			{
+				// E = rotateLeft(A, 5) + G(B, C, D) + E + X[idx++] + Y3
+				// B = rotateLeft(B, 30)
+				E += (A << 5 | (A >> 27)) + G(B, C, D) + _hashValue[idx++] + Y3;
+				B = B << 30 | (B >> 2);
+
+				D += (E << 5 | (E >> 27)) + G(A, B, C) + _hashValue[idx++] + Y3;
+				A = A << 30 | (A >> 2);
+
+				C += (D << 5 | (D >> 27)) + G(E, A, B) + _hashValue[idx++] + Y3;
+				E = E << 30 | (E >> 2);
+
+				B += (C << 5 | (C >> 27)) + G(D, E, A) + _hashValue[idx++] + Y3;
+				D = D << 30 | (D >> 2);
+
+				A += (B << 5 | (B >> 27)) + G(C, D, E) + _hashValue[idx++] + Y3;
+				C = C << 30 | (C >> 2);
+			}
+
+			//
+			// round 4
+			//
+			for (int j = 0; j < 4; j++)
+			{
+				// E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y4
+				// B = rotateLeft(B, 30)
+				E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y4;
+				B = B << 30 | (B >> 2);
+
+				D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y4;
+				A = A << 30 | (A >> 2);
+
+				C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y4;
+				E = E << 30 | (E >> 2);
+
+				B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y4;
+				D = D << 30 | (D >> 2);
+
+				A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y4;
+				C = C << 30 | (C >> 2);
+			}
+
+			H1 += A;
+			H2 += B;
+			H3 += C;
+			H4 += D;
+			H5 += E;
+
+			//
+			// reset start of the buffer.
+			//
+			this._offset = 0;
+			Array.Clear(_hashValue, 0, 16);
+		}
+
+		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);
+		}
+	}
+}

+ 1 - 1
Renci.SshClient/Renci.SshNet/Security/HMacMD5.cs

@@ -33,7 +33,7 @@ namespace Renci.SshNet.Security
         /// <param name="key">The hash key.</param>
         public override void Init(IEnumerable<byte> key)
         {
-            this._hash = new Renci.SshNet.Security.Cryptography.HMAC<Renci.SshNet.Security.Cryptography.MD5>(key.Take(16).ToArray());
+            this._hash = new Renci.SshNet.Security.Cryptography.HMAC<Renci.SshNet.Security.Cryptography.MD5Hash>(key.Take(16).ToArray());
         }
 
         /// <summary>

+ 1 - 1
Renci.SshClient/Renci.SshNet/Security/HMacSha1.cs

@@ -33,7 +33,7 @@ namespace Renci.SshNet.Security
         /// <param name="key">The hash key.</param>
         public override void Init(IEnumerable<byte> key)
         {
-            this._hash = new HMACSHA1(key.Take(20).ToArray());
+            this._hash = new Renci.SshNet.Security.Cryptography.HMAC<Renci.SshNet.Security.Cryptography.SHA1Hash>(key.Take(20).ToArray());
         }
 
         /// <summary>

+ 3 - 7
Renci.SshClient/Renci.SshNet/Security/KeyExchange.cs

@@ -291,14 +291,10 @@ namespace Renci.SshNet.Security
         /// <returns>Hashed bytes</returns>
         protected virtual byte[] Hash(IEnumerable<byte> hashBytes)
         {
-            using (var md = new SHA1CryptoServiceProvider())
+            using (var sha1 = new Renci.SshNet.Security.Cryptography.SHA1Hash())
             {
-                using (var cs = new System.Security.Cryptography.CryptoStream(System.IO.Stream.Null, md, System.Security.Cryptography.CryptoStreamMode.Write))
-                {
-                    var hashData = hashBytes.ToArray();
-                    cs.Write(hashData, 0, hashData.Length);
-                }
-                return md.Hash;
+                var hashData = hashBytes.ToArray();
+                return sha1.ComputeHash(hashData, 0, hashData.Length);
             }
         }
 

+ 4 - 0
Renci.SshClient/Renci.SshNet/Session.cs

@@ -37,7 +37,11 @@ namespace Renci.SshNet
 
         private static RNGCryptoServiceProvider _randomizer = new System.Security.Cryptography.RNGCryptoServiceProvider();
 
+#if SILVERLIGHT
+        private static Regex _serverVersionRe = new Regex("^SSH-(?<protoversion>[^-]+)-(?<softwareversion>.+)( SP.+)?$");
+#else
         private static Regex _serverVersionRe = new Regex("^SSH-(?<protoversion>[^-]+)-(?<softwareversion>.+)( SP.+)?$", RegexOptions.Compiled);
+#endif
 
         /// <summary>
         /// Controls how many authentication attempts can take place at the same time.