浏览代码

Add RsaKey and DsaKey classes
Add HostAlgorithm class for host key authentication and possible for certificate authentication in the future
Refactor public/private key logic

olegkap_cp 14 年之前
父节点
当前提交
745bc9e2bc
共有 28 个文件被更改,包括 806 次插入991 次删除
  1. 0 1
      Renci.SshClient/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj
  2. 0 16
      Renci.SshClient/Renci.SshNet.Tests/Security/TestCryptoKey.cs
  3. 4 3
      Renci.SshClient/Renci.SshNet.Tests/Security/TestHostKey.cs
  4. 80 31
      Renci.SshClient/Renci.SshNet/Common/DerData.cs
  5. 10 4
      Renci.SshClient/Renci.SshNet/ConnectionInfo.cs
  6. 3 0
      Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/KeepAliveRequestInfo.cs
  7. 4 4
      Renci.SshClient/Renci.SshNet/PrivateKeyConnectionInfo.cs
  8. 8 39
      Renci.SshClient/Renci.SshNet/PrivateKeyFile.cs
  9. 12 21
      Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj
  10. 53 0
      Renci.SshClient/Renci.SshNet/Security/CertificateHostAlgorithm.cs
  11. 0 27
      Renci.SshClient/Renci.SshNet/Security/CryptoKey.cs
  12. 0 62
      Renci.SshClient/Renci.SshNet/Security/CryptoPrivateKey.cs
  13. 0 155
      Renci.SshClient/Renci.SshNet/Security/CryptoPrivateKeyDss.cs
  14. 0 166
      Renci.SshClient/Renci.SshNet/Security/CryptoPrivateKeyRsa.cs
  15. 0 18
      Renci.SshClient/Renci.SshNet/Security/CryptoPublicKey.cs
  16. 0 173
      Renci.SshClient/Renci.SshNet/Security/CryptoPublicKeyDss.cs
  17. 0 155
      Renci.SshClient/Renci.SshNet/Security/CryptoPublicKeyRsa.cs
  18. 9 2
      Renci.SshClient/Renci.SshNet/Security/Cryptography/CipherDigitalSignature.cs
  19. 17 54
      Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/RsaCipher.cs
  20. 2 2
      Renci.SshClient/Renci.SshNet/Security/Cryptography/DigitalSignature.cs
  21. 32 35
      Renci.SshClient/Renci.SshNet/Security/Cryptography/DsaDigitalSignature.cs
  22. 125 0
      Renci.SshClient/Renci.SshNet/Security/Cryptography/DsaKey.cs
  23. 87 0
      Renci.SshClient/Renci.SshNet/Security/Cryptography/Key.cs
  24. 3 20
      Renci.SshClient/Renci.SshNet/Security/Cryptography/RsaDigitalSignature.cs
  25. 139 0
      Renci.SshClient/Renci.SshNet/Security/Cryptography/RsaKey.cs
  26. 49 0
      Renci.SshClient/Renci.SshNet/Security/HostAlgorithm.cs
  27. 4 3
      Renci.SshClient/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs
  28. 165 0
      Renci.SshClient/Renci.SshNet/Security/KeyHostAlgorithm.cs

+ 0 - 1
Renci.SshClient/Renci.SshNet.Tests/Renci.SshNet.Tests.csproj

@@ -55,7 +55,6 @@
   <ItemGroup>
     <Compile Include="ConnectionTest.cs" />
     <Compile Include="Security\TestCipher.cs" />
-    <Compile Include="Security\TestCryptoKey.cs" />
     <Compile Include="Security\TestHMac.cs" />
     <Compile Include="Security\TestHostKey.cs" />
     <Compile Include="Security\TestKeyExchange.cs" />

文件差异内容过多而无法显示
+ 0 - 16
Renci.SshClient/Renci.SshNet.Tests/Security/TestCryptoKey.cs


+ 4 - 3
Renci.SshClient/Renci.SshNet.Tests/Security/TestHostKey.cs

@@ -5,6 +5,7 @@ using System.Text;
 using Microsoft.VisualStudio.TestTools.UnitTesting;
 using Renci.SshNet.Security;
 using Renci.SshNet.Tests.Properties;
+using Renci.SshNet.Security.Cryptography;
 
 namespace Renci.SshNet.Tests.Security
 {
@@ -16,8 +17,8 @@ namespace Renci.SshNet.Tests.Security
         {
             var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
             connectionInfo.HostKeyAlgorithms.Clear();
-            connectionInfo.HostKeyAlgorithms.Add("ssh-rsa", typeof(CryptoPublicKeyRsa));
-
+            connectionInfo.HostKeyAlgorithms.Add("ssh-rsa", (data) => { return new KeyHostAlgorithm("ssh-rsa", new RsaKey(), data); });
+            
             using (var client = new SshClient(connectionInfo))
             {
                 client.Connect();
@@ -30,7 +31,7 @@ namespace Renci.SshNet.Tests.Security
         {
             var connectionInfo = new PasswordConnectionInfo(Resources.HOST, 22, Resources.USERNAME, Resources.PASSWORD);
             connectionInfo.HostKeyAlgorithms.Clear();
-            connectionInfo.HostKeyAlgorithms.Add("ssh-dss", typeof(CryptoPublicKeyDss));
+            connectionInfo.HostKeyAlgorithms.Add("ssh-dss", (data) => { return new KeyHostAlgorithm("ssh-dss", new DsaKey(), data); });
 
             using (var client = new SshClient(connectionInfo))
             {

+ 80 - 31
Renci.SshClient/Renci.SshNet/Common/DerData.cs

@@ -8,7 +8,7 @@ namespace Renci.SshNet.Common
     /// <summary>
     /// Base class for DER encoded data.
     /// </summary>
-    public abstract class DerData
+    public class DerData
     {
         private const byte CONSTRUCTED = 0x20;
 
@@ -44,13 +44,48 @@ namespace Renci.SshNet.Common
         private List<byte> _data;
 
         private int _readerIndex = 0;
+        private int _lastIndex;
 
-        public byte[] Encode()
+        /// <summary>
+        /// Gets a value indicating whether end of data is reached.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if end of data is reached; otherwise, <c>false</c>.
+        /// </value>
+        public bool IsEndOfData
+        {
+            get
+            {
+                return this._readerIndex >= this._lastIndex;
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="DerData"/> class.
+        /// </summary>
+        public DerData()
         {
             this._data = new List<byte>();
+        }
 
-            this.SaveData();
+        /// <summary>
+        /// Initializes a new instance of the <see cref="DerData"/> class.
+        /// </summary>
+        /// <param name="data">DER encoded data.</param>
+        public DerData(byte[] data)
+        {
+            this._data = new List<byte>(data);
+            var dataType = this.ReadByte();
+            var length = this.ReadLength();
+            this._lastIndex = this._readerIndex + length;
+        }
 
+        /// <summary>
+        /// Encodes written data as DER byte array.
+        /// </summary>
+        /// <returns></returns>
+        public byte[] Encode()
+        {
             var length = this._data.Count();
             var lengthBytes = this.GetLength(length);
 
@@ -60,31 +95,28 @@ namespace Renci.SshNet.Common
             return this._data.ToArray();
         }
 
-        public void Decode(byte[] data)
+        /// <summary>
+        /// Reads next mpint data type from internal buffer.
+        /// </summary>
+        /// <returns>mpint read.</returns>
+        public BigInteger ReadBigInteger()
         {
-            this._data = new List<byte>(data);
-            this._readerIndex = 0;
-            var dataType = this.ReadByte();
-            var length = this.ReadLength();
+            var type = this.ReadByte();
+            if (type != INTEGER)
+                throw new InvalidOperationException("Invalid data type, INTEGER(02) is expected.");
 
-            this.LoadData();
-        }
+            var length = this.ReadLength();
 
-        /// <summary>
-        /// Called when type specific data need to be loaded.
-        /// </summary>
-        protected abstract void LoadData();
+            var data = this.ReadBytes(length);
 
-        /// <summary>
-        /// Called when type specific data need to be saved.
-        /// </summary>
-        protected abstract void SaveData();
+            return new BigInteger(data.Reverse().ToArray());
+        }
 
         /// <summary>
-        /// Reads next mpint data type from internal buffer.
+        /// Reads next int data type from internal buffer.
         /// </summary>
-        /// <returns>mpint read.</returns>
-        protected BigInteger ReadBigInt()
+        /// <returns>int read.</returns>
+        public int ReadInteger()
         {
             var type = this.ReadByte();
             if (type != INTEGER)
@@ -94,14 +126,27 @@ namespace Renci.SshNet.Common
 
             var data = this.ReadBytes(length);
 
-            return new BigInteger(data.Reverse().ToArray());
+            if (length > 4)
+                throw new InvalidOperationException("Integer type cannot occupy more then 4 bytes");
+
+            var result = 0;
+            var shift = (length - 1) * 8;
+            for (int i = 0; i < length; i++)
+            {
+                result |= data[i] << shift;
+                shift -= 8;
+            }
+
+            //return (int)(data[0] << 56 | data[1] << 48 | data[2] << 40 | data[3] << 32 | data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]);
+
+            return result;
         }
 
         /// <summary>
-        /// Writes uint32 data into internal buffer.
+        /// Writes UInt32 data into internal buffer.
         /// </summary>
-        /// <param name="data">uint32 data to write.</param>
-        protected void Write(UInt32 data)
+        /// <param name="data">UInt32 data to write.</param>
+        public void Write(UInt32 data)
         {
             var bytes = data.GetBytes();
             this._data.Add(INTEGER);
@@ -110,7 +155,11 @@ namespace Renci.SshNet.Common
             this.WriteBytes(bytes);
         }
 
-        protected void Write(BigInteger data)
+        /// <summary>
+        /// Writes BigInteger data into internal buffer.
+        /// </summary>
+        /// <param name="data">BigInteger data to write.</param>
+        public void Write(BigInteger data)
         {
             var bytes = data.ToByteArray().Reverse().ToList();
             this._data.Add(INTEGER);
@@ -119,7 +168,11 @@ namespace Renci.SshNet.Common
             this.WriteBytes(bytes);
         }
 
-        protected void Write(DerData data)
+        /// <summary>
+        /// Writes DerData data into internal buffer.
+        /// </summary>
+        /// <param name="data">DerData data to write.</param>
+        public void Write(DerData data)
         {
             throw new NotImplementedException();
         }
@@ -208,9 +261,5 @@ namespace Renci.SshNet.Common
             this._readerIndex += length;
             return result;
         }
-
-
-
-
     }
 }

+ 10 - 4
Renci.SshClient/Renci.SshNet/ConnectionInfo.cs

@@ -62,7 +62,7 @@ namespace Renci.SshNet
         /// <summary>
         /// Gets supported host key algorithms for this connection.
         /// </summary>
-        public IDictionary<string, Type> HostKeyAlgorithms { get; private set; }
+        public IDictionary<string, Func<byte[], HostAlgorithm>> HostKeyAlgorithms { get; private set; }
 
         /// <summary>
         /// Gets supported authentication methods for this connection.
@@ -178,10 +178,16 @@ namespace Renci.SshNet
                 //{"none", typeof(...)},
             };
 
-            this.HostKeyAlgorithms = new Dictionary<string, Type>()
+            this.HostKeyAlgorithms = new Dictionary<string, Func<byte[], HostAlgorithm>>()
             {
-                {"ssh-rsa", typeof(CryptoPublicKeyRsa)},
-                {"ssh-dss", typeof(CryptoPublicKeyDss)}, 
+                {"ssh-rsa", (data) => { return new KeyHostAlgorithm("ssh-rsa", new RsaKey(), data); }},
+                {"ssh-dss", (data) => { return new KeyHostAlgorithm("ssh-dss", new DsaKey(), data); }},
+                //{"x509v3-sign-rsa", () => { ... },
+                //{"x509v3-sign-dss", () => { ... },
+                //{"spki-sign-rsa", () => { ... },
+                //{"spki-sign-dss", () => { ... },
+                //{"pgp-sign-rsa", () => { ... },
+                //{"pgp-sign-dss", () => { ... },
             };
 
             this.AuthenticationMethods = new Dictionary<string, Type>()

+ 3 - 0
Renci.SshClient/Renci.SshNet/Messages/Connection/ChannelRequest/KeepAliveRequestInfo.cs

@@ -5,6 +5,9 @@ using System.Text;
 
 namespace Renci.SshNet.Messages.Connection
 {
+    /// <summary>
+    /// Represents "keepalive@openssh.com" type channel request information
+    /// </summary>
     public class KeepAliveRequestInfo : RequestInfo
     {
         /// <summary>

+ 4 - 4
Renci.SshClient/Renci.SshNet/PrivateKeyConnectionInfo.cs

@@ -75,14 +75,14 @@ namespace Renci.SshNet
                 this._publicKeyRequestMessageResponseWaitHandle.Reset();
                 this._isSignatureRequired = false;
 
-                var message = new RequestMessagePublicKey(ServiceName.Connection, this.Username, keyFile.AlgorithmName, keyFile.PublicKey);
+                var message = new RequestMessagePublicKey(ServiceName.Connection, this.Username, keyFile.HostKey.Name, keyFile.HostKey.Data);
 
                 if (this.KeyFiles.Count < 2)
                 {
                     //  If only one key file provided then send signature for very first request
                     var signatureData = new SignatureData(message, this.Session.SessionId).GetBytes();
 
-                    message.Signature = keyFile.GetSignature(signatureData);
+                    message.Signature = keyFile.HostKey.Sign(signatureData);
                 }
 
                 //  Send public key authentication request
@@ -94,11 +94,11 @@ namespace Renci.SshNet
                 {
                     this._publicKeyRequestMessageResponseWaitHandle.Reset();
 
-                    var signatureMessage = new RequestMessagePublicKey(ServiceName.Connection, this.Username, keyFile.AlgorithmName, keyFile.PublicKey);
+                    var signatureMessage = new RequestMessagePublicKey(ServiceName.Connection, this.Username, keyFile.HostKey.Name, keyFile.HostKey.Data);
 
                     var signatureData = new SignatureData(message, this.Session.SessionId).GetBytes();
 
-                    signatureMessage.Signature = keyFile.GetSignature(signatureData);
+                    signatureMessage.Signature = keyFile.HostKey.Sign(signatureData);
 
                     //  Send public key authentication request with signature
                     this.SendMessage(signatureMessage);

+ 8 - 39
Renci.SshClient/Renci.SshNet/PrivateKeyFile.cs

@@ -27,42 +27,10 @@ namespace Renci.SshNet
         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;
-
-        /// <summary>
-        /// Gets the name of private key algorithm.
-        /// </summary>
-        /// <value>
-        /// The name of the algorithm.
-        /// </value>
-        public string AlgorithmName
-        {
-            get
-            {
-                return this._key.Name;
-            }
-        }
-
-        /// <summary>
-        /// Gets the public key.
-        /// </summary>
-        public byte[] PublicKey
-        {
-            get
-            {
-                return this._key.GetPublicKey().GetBytes().ToArray();
-            }
-        }
-
         /// <summary>
-        /// Gets the signature.
+        /// Gets the host key.
         /// </summary>
-        /// <param name="sessionId">The session id.</param>
-        /// <returns>Signature data</returns>
-        public byte[] GetSignature(IEnumerable<byte> sessionId)
-        {
-            return this._key.GetSignature(sessionId);
-        }
+        public HostAlgorithm HostKey;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="PrivateKeyFile"/> class.
@@ -199,16 +167,14 @@ namespace Renci.SshNet
             switch (keyName)
             {
                 case "RSA":
-                    this._key = new CryptoPrivateKeyRsa();
+                    this.HostKey = new KeyHostAlgorithm("ssh-rsa", new RsaKey(decryptedData.ToArray()));
                     break;
                 case "DSA":
-                    this._key = new CryptoPrivateKeyDss();
+                    this.HostKey = new KeyHostAlgorithm("ssh-dss", new DsaKey(decryptedData.ToArray()));
                     break;
                 default:
                     throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Key '{0}' is not supported.", keyName));
             }
-
-            this._key.Load(decryptedData);
         }
 
         /// <summary>
@@ -224,10 +190,13 @@ namespace Renci.SshNet
         {
             if (cipherInfo == null)
                 throw new ArgumentNullException("cipherInfo");
-            
+
             if (cipherData == null)
                 throw new ArgumentNullException("cipherData");
 
+            if (binarySalt == null)
+                throw new ArgumentNullException("binarySalt");
+
             List<byte> cipherKey = new List<byte>();
 
             using (var md5 = new MD5Hash())

+ 12 - 21
Renci.SshClient/Renci.SshNet/Renci.SshNet.csproj

@@ -110,6 +110,7 @@
     <Compile Include="Security\Algorithm.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Security\CertificateHostAlgorithm.cs" />
     <Compile Include="Security\Cryptography\CipherDigitalSignature.cs" />
     <Compile Include="Security\Cryptography\Ciphers\AesCipher.cs" />
     <Compile Include="Security\Cryptography\Ciphers\Arc4Cipher.cs" />
@@ -129,6 +130,15 @@
     <Compile Include="Security\Cryptography\Ciphers\RsaCipher.cs" />
     <Compile Include="Security\Cryptography\Ciphers\SerpentCipher.cs" />
     <Compile Include="Security\Cryptography\DsaDigitalSignature.cs" />
+    <Compile Include="Security\Cryptography\DsaKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\Cryptography\Key.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Security\Cryptography\RsaKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
     <Compile Include="Security\Cryptography\StreamCipher.cs" />
     <Compile Include="Security\Cryptography\SymmetricCipher.cs" />
     <Compile Include="Security\Cryptography\Ciphers\TripleDesCipher.cs" />
@@ -151,27 +161,7 @@
     <Compile Include="Security\Cryptography\Hashes\SHA256Hash.cs">
       <SubType>Code</SubType>
     </Compile>
-    <Compile Include="Security\CryptoKey.cs">
-      <SubType>Code</SubType>
-    </Compile>
-    <Compile Include="Security\CryptoPrivateKey.cs">
-      <SubType>Code</SubType>
-    </Compile>
-    <Compile Include="Security\CryptoPrivateKeyDss.cs">
-      <SubType>Code</SubType>
-    </Compile>
-    <Compile Include="Security\CryptoPrivateKeyRsa.cs">
-      <SubType>Code</SubType>
-    </Compile>
-    <Compile Include="Security\CryptoPublicKey.cs">
-      <SubType>Code</SubType>
-    </Compile>
-    <Compile Include="Security\CryptoPublicKeyDss.cs">
-      <SubType>Code</SubType>
-    </Compile>
-    <Compile Include="Security\CryptoPublicKeyRsa.cs">
-      <SubType>Code</SubType>
-    </Compile>
+    <Compile Include="Security\HostAlgorithm.cs" />
     <Compile Include="Security\KeyExchange.cs">
       <SubType>Code</SubType>
     </Compile>
@@ -190,6 +180,7 @@
     <Compile Include="Security\KeyExchangeDiffieHellmanGroupExchangeSha256.cs">
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Security\KeyHostAlgorithm.cs" />
     <Compile Include="Shell.NET40.cs" />
     <Compile Include="SftpClient.NET40.cs" />
     <Compile Include="PasswordConnectionInfo.NET40.cs" />

+ 53 - 0
Renci.SshClient/Renci.SshNet/Security/CertificateHostAlgorithm.cs

@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Renci.SshNet.Security
+{
+    /// <summary>
+    /// Implements certificate support for host algorithm.
+    /// </summary>
+    public class CertificateHostAlgorithm : HostAlgorithm
+    {
+        /// <summary>
+        /// Gets the host key data.
+        /// </summary>
+        public override byte[] Data
+        {
+            get { throw new NotImplementedException(); }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="CertificateHostAlgorithm"/> class.
+        /// </summary>
+        /// <param name="name">The host key name.</param>
+        public CertificateHostAlgorithm(string name)
+            : base(name)
+        {
+
+        }
+
+        /// <summary>
+        /// Signs the specified data.
+        /// </summary>
+        /// <param name="data">The data.</param>
+        /// <returns></returns>
+        public override byte[] Sign(byte[] data)
+        {
+            throw new NotImplementedException();
+        }
+
+        /// <summary>
+        /// Verifies the signature.
+        /// </summary>
+        /// <param name="data">The data.</param>
+        /// <param name="signature">The signature.</param>
+        /// <returns></returns>
+        public override bool VerifySignature(byte[] data, byte[] signature)
+        {
+            throw new NotImplementedException();
+        }
+
+    }
+}

+ 0 - 27
Renci.SshClient/Renci.SshNet/Security/CryptoKey.cs

@@ -1,27 +0,0 @@
-using System.Collections.Generic;
-
-namespace Renci.SshNet.Security
-{
-    /// <summary>
-    /// Represents base class for public and private keys
-    /// </summary>
-    public abstract class CryptoKey
-    {
-        /// <summary>
-        /// Gets key name.
-        /// </summary>
-        public abstract string Name { get; }
-
-        /// <summary>
-        /// Loads key specific data.
-        /// </summary>
-        /// <param name="data">The data.</param>
-        public abstract void Load(IEnumerable<byte> data);
-
-        /// <summary>
-        /// Gets key data byte array.
-        /// </summary>
-        /// <returns>The data byte array.</returns>
-        public abstract IEnumerable<byte> GetBytes();
-    }
-}

+ 0 - 62
Renci.SshClient/Renci.SshNet/Security/CryptoPrivateKey.cs

@@ -1,62 +0,0 @@
-using System.Collections.Generic;
-using Renci.SshNet.Common;
-
-namespace Renci.SshNet.Security
-{
-    /// <summary>
-    /// Represents base class for private keys
-    /// </summary>
-    public abstract class CryptoPrivateKey : CryptoKey
-    {
-        /// <summary>
-        /// Gets the public key.
-        /// </summary>
-        /// <returns></returns>
-        public abstract CryptoPublicKey GetPublicKey();
-
-        /// <summary>
-        /// Gets the signature.
-        /// </summary>
-        /// <param name="key">The key data bytes.</param>
-        /// <returns></returns>
-        public abstract byte[] GetSignature(IEnumerable<byte> key);
-
-        /// <summary>
-        /// Represents signature key data structure
-        /// </summary>
-        protected class SignatureKeyData : SshData
-        {
-            /// <summary>
-            /// Gets or sets the name of the algorithm.
-            /// </summary>
-            /// <value>
-            /// The name of the algorithm.
-            /// </value>
-            public string AlgorithmName { get; set; }
-
-            /// <summary>
-            /// Gets or sets the signature.
-            /// </summary>
-            /// <value>
-            /// The signature.
-            /// </value>
-            public byte[] Signature { get; set; }
-
-            /// <summary>
-            /// Called when type specific data need to be loaded.
-            /// </summary>
-            protected override void LoadData()
-            {
-            }
-
-            /// <summary>
-            /// Called when type specific data need to be saved.
-            /// </summary>
-            protected override void SaveData()
-            {
-                this.Write(this.AlgorithmName);
-                this.WriteBinaryString(this.Signature);
-            }
-        }
-    }
-}

+ 0 - 155
Renci.SshClient/Renci.SshNet/Security/CryptoPrivateKeyDss.cs

@@ -1,155 +0,0 @@
-using System;
-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
-{
-    /// <summary>
-    /// Represents DSS private key
-    /// </summary>
-    internal class CryptoPrivateKeyDss : CryptoPrivateKey
-    {
-        private byte[] _p;
-        private byte[] _q;
-        private byte[] _g;
-        private byte[] _publicKey;
-        private byte[] _privateKey;
-
-        /// <summary>
-        /// Gets key name.
-        /// </summary>
-        public override string Name
-        {
-            get { return "ssh-dss"; }
-        }
-
-        /// <summary>
-        /// Loads key specific data.
-        /// </summary>
-        /// <param name="data">The data.</param>
-        public override void Load(IEnumerable<byte> data)
-        {
-            MemoryStream ms = null;
-            try
-            {
-                ms = new MemoryStream(data.ToArray());
-                using (var binr = new BinaryReader(ms)) //wrap Memory Stream with BinaryReader for easy reading
-                {
-                    byte bt = 0;
-                    ushort twobytes = 0;
-                    int elems = 0;
-
-                    twobytes = binr.ReadUInt16();
-                    if (twobytes == 0x8130)	//data read as little endian order (actual data order for Sequence is 30 81)
-                        binr.ReadByte();	//advance 1 byte
-                    else if (twobytes == 0x8230)
-                        binr.ReadInt16();	//advance 2 bytes
-                    else
-                        throw new SshException("DSS key is not valid for use in specified state");                    
-                    
-                    twobytes = binr.ReadUInt16();
-                    if (twobytes != 0x0102)	//version number
-                        throw new SshException("DSS key version is not supported.");
-
-                    bt = binr.ReadByte();
-                    if (bt != 0x00)
-                        throw new SshException("DSS key is not valid for use in specified state");                    
-
-                    //------  all private key components are Integer sequences ----
-                    elems = CryptoPrivateKeyDss.GetIntegerSize(binr);
-                    this._p = binr.ReadBytes(elems);
-
-                    elems = CryptoPrivateKeyDss.GetIntegerSize(binr);
-                    this._q = binr.ReadBytes(elems);
-
-                    elems = CryptoPrivateKeyDss.GetIntegerSize(binr);
-                    this._g = binr.ReadBytes(elems);
-
-                    elems = CryptoPrivateKeyDss.GetIntegerSize(binr);
-                    this._publicKey = binr.ReadBytes(elems);
-
-                    elems = CryptoPrivateKeyDss.GetIntegerSize(binr);
-                    this._privateKey = binr.ReadBytes(elems);
-                }
-            }
-            finally
-            {
-                if (ms != null)
-                {
-                    ms.Dispose();
-                    ms = null;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets the public key.
-        /// </summary>
-        /// <returns></returns>
-        public override CryptoPublicKey GetPublicKey()
-        {
-            return new CryptoPublicKeyDss(this._p, this._q, this._g, this._publicKey);
-        }
-
-        /// <summary>
-        /// Gets the signature.
-        /// </summary>
-        /// <param name="key">The key data bytes.</param>
-        /// <returns></returns>
-        public override byte[] GetSignature(IEnumerable<byte> key)
-        {
-            var ss1 = new DsaDigitalSignature(this._p, this._q, this._g, this._privateKey, null);
-            var signature = ss1.CreateSignature(key.ToArray());
-            return new SignatureKeyData
-            {
-                AlgorithmName = this.Name,
-                Signature = signature,
-            }.GetBytes().ToArray();
-        }
-
-        /// <summary>
-        /// Gets key data byte array.
-        /// </summary>
-        /// <returns>
-        /// The data byte array.
-        /// </returns>
-        public override IEnumerable<byte> GetBytes()
-        {
-            throw new NotImplementedException();
-        }
-
-        private static int GetIntegerSize(BinaryReader binr)
-        {
-            byte bt = 0;
-            byte lowbyte = 0x00;
-            byte highbyte = 0x00;
-            int count = 0;
-            bt = binr.ReadByte();
-            if (bt != 0x02)		//expect integer
-                return 0;
-            bt = binr.ReadByte();
-
-            if (bt == 0x81)
-                count = binr.ReadByte();	// data size in next byte
-            else
-                if (bt == 0x82)
-                {
-                    highbyte = binr.ReadByte();	// data size in next 2 bytes
-                    lowbyte = binr.ReadByte();
-                    byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
-                    count = (int)(modint[3] << 24 | modint[2] << 16 | modint[1] << 8 | modint[0]);
-                }
-                else
-                {
-                    count = bt;		// we already have the data size
-                }
-
-            return count;
-        }
-
-    }
-}

+ 0 - 166
Renci.SshClient/Renci.SshNet/Security/CryptoPrivateKeyRsa.cs

@@ -1,166 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using Renci.SshNet.Common;
-using Renci.SshNet.Security.Cryptography;
-using Renci.SshNet.Security.Cryptography.Ciphers;
-
-namespace Renci.SshNet.Security
-{
-    /// <summary>
-    /// Represents RSA private key
-    /// </summary>
-    internal class CryptoPrivateKeyRsa : CryptoPrivateKey
-    {
-        private byte[] _modulus;
-        private byte[] _exponent;
-        private byte[] _dValue;
-        private byte[] _pValue;
-        private byte[] _qValue;
-        private byte[] _dpValue;
-        private byte[] _dqValue;
-        private byte[] _inverseQ;
-
-        /// <summary>
-        /// Gets key name.
-        /// </summary>
-        public override string Name
-        {
-            get { return "ssh-rsa"; }
-        }
-
-        /// <summary>
-        /// Loads key specific data.
-        /// </summary>
-        /// <param name="data">The data.</param>
-        public override void Load(IEnumerable<byte> data)
-        {
-            MemoryStream ms = null;
-            try
-            {
-                ms = new MemoryStream(data.ToArray());
-                using (var binr = new BinaryReader(ms))
-                {
-                    byte bt = 0;
-                    ushort twobytes = 0;
-                    int elems = 0;
-
-                    twobytes = binr.ReadUInt16();
-                    if (twobytes == 0x8130)	//data read as little endian order (actual data order for Sequence is 30 81)
-                        binr.ReadByte();	//advance 1 byte
-                    else if (twobytes == 0x8230)
-                        binr.ReadInt16();	//advance 2 bytes
-                    else
-                        throw new SshException("RSA key is not valid for use in specified state");
-
-                    twobytes = binr.ReadUInt16();
-                    if (twobytes != 0x0102)	//version number
-                        throw new SshException("RSA key version is not supported.");
-                    
-                    bt = binr.ReadByte();
-                    if (bt != 0x00)
-                        throw new SshException("RSA key is not valid for use in specified state");
-
-                    //------  all private key components are Integer sequences ----
-                    elems = CryptoPrivateKeyRsa.GetIntegerSize(binr);
-                    this._modulus = binr.ReadBytes(elems);
-
-                    elems = CryptoPrivateKeyRsa.GetIntegerSize(binr);
-                    this._exponent = binr.ReadBytes(elems);
-
-                    elems = CryptoPrivateKeyRsa.GetIntegerSize(binr);
-                    this._dValue = binr.ReadBytes(elems);
-
-                    elems = CryptoPrivateKeyRsa.GetIntegerSize(binr);
-                    this._pValue = binr.ReadBytes(elems);
-
-                    elems = CryptoPrivateKeyRsa.GetIntegerSize(binr);
-                    this._qValue = binr.ReadBytes(elems);
-
-                    elems = CryptoPrivateKeyRsa.GetIntegerSize(binr);
-                    this._dpValue = binr.ReadBytes(elems);
-
-                    elems = CryptoPrivateKeyRsa.GetIntegerSize(binr);
-                    this._dqValue = binr.ReadBytes(elems);
-
-                    elems = CryptoPrivateKeyRsa.GetIntegerSize(binr);
-                    this._inverseQ = binr.ReadBytes(elems);
-                }
-            }
-            finally
-            {
-                if (ms != null)
-                {
-                    ms.Dispose();
-                    ms = null;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets the public key.
-        /// </summary>
-        /// <returns></returns>
-        public override CryptoPublicKey GetPublicKey()
-        {
-            return new CryptoPublicKeyRsa(this._modulus, this._exponent);
-        }
-
-        /// <summary>
-        /// Gets the signature.
-        /// </summary>
-        /// <param name="key">The key data bytes.</param>
-        /// <returns></returns>
-        public override byte[] GetSignature(IEnumerable<byte> key)
-        {
-            var signature = new RsaDigitalSignature(this._exponent, this._modulus, this._dValue, this._dpValue, this._dqValue, this._inverseQ, this._pValue, this._qValue);
-
-            return new SignatureKeyData
-            {
-                AlgorithmName = this.Name,
-                Signature = signature.CreateSignature(key.ToArray()),
-            }.GetBytes().ToArray();
-        }
-
-        /// <summary>
-        /// Gets key data byte array.
-        /// </summary>
-        /// <returns>
-        /// The data byte array.
-        /// </returns>
-        public override IEnumerable<byte> GetBytes()
-        {
-            throw new NotImplementedException();
-        }
-
-        private static int GetIntegerSize(BinaryReader binr)
-        {
-            byte bt = 0;
-            byte lowbyte = 0x00;
-            byte highbyte = 0x00;
-            int count = 0;
-            bt = binr.ReadByte();
-            if (bt != 0x02)		//expect integer
-                return 0;
-            bt = binr.ReadByte();
-
-            if (bt == 0x81)
-                count = binr.ReadByte();	// data size in next byte
-            else
-                if (bt == 0x82)
-                {
-                    highbyte = binr.ReadByte();	// data size in next 2 bytes
-                    lowbyte = binr.ReadByte();
-                    byte[] modint = { lowbyte, highbyte, 0x00, 0x00 };
-                    count = (int)(modint[3] << 24 | modint[2] << 16 | modint[1] << 8 | modint[0]);
-                }
-                else
-                {
-                    count = bt;		// we already have the data size
-                }
-
-            return count;
-        }
-    }
-}

+ 0 - 18
Renci.SshClient/Renci.SshNet/Security/CryptoPublicKey.cs

@@ -1,18 +0,0 @@
-using System.Collections.Generic;
-
-namespace Renci.SshNet.Security
-{
-    /// <summary>
-    /// Represents base class for public keys
-    /// </summary>
-    public abstract class CryptoPublicKey : CryptoKey
-    {
-        /// <summary>
-        /// Verifies the signature.
-        /// </summary>
-        /// <param name="hash">The hash.</param>
-        /// <param name="signature">The signature.</param>
-        /// <returns>true if signature verified; otherwise false.</returns>
-        public abstract bool VerifySignature(IEnumerable<byte> hash, IEnumerable<byte> signature);
-    }
-}

+ 0 - 173
Renci.SshClient/Renci.SshNet/Security/CryptoPublicKeyDss.cs

@@ -1,173 +0,0 @@
-using System;
-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
-{
-    /// <summary>
-    /// Represents DSS public key
-    /// </summary>
-    public class CryptoPublicKeyDss : CryptoPublicKey
-    {
-        private byte[] _p;
-        private byte[] _q;
-        private byte[] _g;
-        private byte[] _publicKey;
-
-        /// <summary>
-        /// Gets key name.
-        /// </summary>
-        public override string Name
-        {
-            get { return "ssh-dss"; }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="CryptoPublicKeyDss"/> class.
-        /// </summary>
-        public CryptoPublicKeyDss()
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="CryptoPublicKeyDss"/> class.
-        /// </summary>
-        /// <param name="p">The p value.</param>
-        /// <param name="q">The q value.</param>
-        /// <param name="g">The g value.</param>
-        /// <param name="publicKey">The public key value.</param>
-        public CryptoPublicKeyDss(byte[] p, byte[] q, byte[] g, byte[] publicKey)
-        {
-            this._p = p;
-            this._q = q;
-            this._g = g;
-            this._publicKey = publicKey;
-        }
-
-        /// <summary>
-        /// Loads key specific data.
-        /// </summary>
-        /// <param name="data">The data.</param>
-        public override void Load(IEnumerable<byte> data)
-        {
-            MemoryStream ms = null;
-            try
-            {
-                ms = new MemoryStream(data.ToArray());
-                using (var br = new BinaryReader(ms))
-                {
-
-                    var pl = (uint)(br.ReadByte() << 24 | br.ReadByte() << 16 | br.ReadByte() << 8 | br.ReadByte());
-
-                    _p = br.ReadBytes((int)pl);
-
-                    var ql = (uint)(br.ReadByte() << 24 | br.ReadByte() << 16 | br.ReadByte() << 8 | br.ReadByte());
-
-                    _q = br.ReadBytes((int)ql);
-
-                    var gl = (uint)(br.ReadByte() << 24 | br.ReadByte() << 16 | br.ReadByte() << 8 | br.ReadByte());
-
-                    _g = br.ReadBytes((int)gl);
-
-                    var xl = (uint)(br.ReadByte() << 24 | br.ReadByte() << 16 | br.ReadByte() << 8 | br.ReadByte());
-
-                    _publicKey = br.ReadBytes((int)xl);
-                }
-            }
-            finally
-            {
-                if (ms != null)
-                {
-                    ms.Dispose();
-                    ms = null;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Verifies the signature.
-        /// </summary>
-        /// <param name="hash">The hash.</param>
-        /// <param name="signature">The signature.</param>
-        /// <returns>
-        /// true if signature verified; otherwise false.
-        /// </returns>
-        public override bool VerifySignature(IEnumerable<byte> hash, IEnumerable<byte> signature)
-        {
-
-            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;
-            }
-
-            var sig1 = new DsaDigitalSignature(_p, _q, _g, null, _publicKey);
-            return sig1.VerifySignature(hash.ToArray(), sig);
-        }
-
-        /// <summary>
-        /// Gets key data byte array.
-        /// </summary>
-        /// <returns>
-        /// The data byte array.
-        /// </returns>
-        public override IEnumerable<byte> GetBytes()
-        {
-            return new DsaPublicKeyData
-            {
-                P = this._p,
-                Q = this._q,
-                G = this._g,
-                Public = this._publicKey,
-            }.GetBytes();
-        }
-
-        private class DsaPublicKeyData : SshData
-        {
-            public byte[] P { get; set; }
-
-            public byte[] Q { get; set; }
-
-            public byte[] G { get; set; }
-
-            public byte[] Public { get; set; }
-
-            protected override void LoadData()
-            {
-            }
-
-            protected override void SaveData()
-            {
-                this.Write("ssh-dss");
-                this.WriteBinaryString(this.P);
-                this.WriteBinaryString(this.Q);
-                this.WriteBinaryString(this.G);
-                this.WriteBinaryString(this.Public);
-            }
-        }
-    }
-}

+ 0 - 155
Renci.SshClient/Renci.SshNet/Security/CryptoPublicKeyRsa.cs

@@ -1,155 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Security.Cryptography;
-using Renci.SshNet.Common;
-using Renci.SshNet.Security.Cryptography;
-using Renci.SshNet.Security.Cryptography.Ciphers;
-
-namespace Renci.SshNet.Security
-{
-    /// <summary>
-    /// Represents RSA public key
-    /// </summary>
-    public class CryptoPublicKeyRsa : CryptoPublicKey
-    {
-        private byte[] _modulus;
-
-        private byte[] _exponent;
-
-        /// <summary>
-        /// Gets key name.
-        /// </summary>
-        public override string Name
-        {
-            get { return "ssh-rsa"; }
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="CryptoPublicKeyRsa"/> class.
-        /// </summary>
-        public CryptoPublicKeyRsa()
-        {
-
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="CryptoPublicKeyRsa"/> class.
-        /// </summary>
-        /// <param name="modulus">The modulus.</param>
-        /// <param name="exponent">The exponent.</param>
-        internal CryptoPublicKeyRsa(byte[] modulus, byte[] exponent)
-        {
-            this._modulus = modulus;
-            this._exponent = exponent;
-        }
-
-        /// <summary>
-        /// Loads key specific data.
-        /// </summary>
-        /// <param name="data">The data.</param>
-        public override void Load(IEnumerable<byte> data)
-        {
-            MemoryStream ms = null;
-            try
-            {
-                ms = new MemoryStream(data.ToArray());
-                using (var br = new BinaryReader(ms))
-                {
-                    var el = (uint)(br.ReadByte() << 24 | br.ReadByte() << 16 | br.ReadByte() << 8 | br.ReadByte());
-
-                    this._exponent = br.ReadBytes((int)el);
-
-                    var ml = (uint)(br.ReadByte() << 24 | br.ReadByte() << 16 | br.ReadByte() << 8 | br.ReadByte());
-
-                    this._modulus = br.ReadBytes((int)ml);
-                }
-            }
-            finally
-            {
-                if (ms != null)
-                {
-                    ms.Dispose();
-                    ms = null;
-                }
-            }
-        }
-
-        /// <summary>
-        /// Verifies the signature.
-        /// </summary>
-        /// <param name="hash">The hash.</param>
-        /// <param name="signature">The signature.</param>
-        /// <returns>
-        /// true if signature verified; otherwise false.
-        /// </returns>
-        public override bool VerifySignature(IEnumerable<byte> hash, IEnumerable<byte> signature)
-        {
-            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;
-            }
-
-            var sig1 = new RsaDigitalSignature(this._exponent, this._modulus);
-
-            return sig1.VerifySignature(hash.ToArray(), sig);
-
-        }
-
-        /// <summary>
-        /// Gets key data byte array.
-        /// </summary>
-        /// <returns>
-        /// The data byte array.
-        /// </returns>
-        public override IEnumerable<byte> GetBytes()
-        {
-            return new RsaPublicKeyData
-            {
-                E = this._exponent,
-                Modulus = this._modulus,
-            }.GetBytes();
-        }
-
-        private class RsaPublicKeyData : SshData
-        {
-            public byte[] Modulus { get; set; }
-
-            public byte[] E { get; set; }
-
-            protected override void LoadData()
-            {
-            }
-
-            protected override void SaveData()
-            {
-                this.Write("ssh-rsa");
-                this.WriteBinaryString(this.E);
-                this.WriteBinaryString(this.Modulus);
-            }
-        }
-
-    }
-}

+ 9 - 2
Renci.SshClient/Renci.SshNet/Security/Cryptography/CipherDigitalSignature.cs

@@ -22,6 +22,12 @@ namespace Renci.SshNet.Security.Cryptography
         /// <param name="cipher">The cipher.</param>
         public CipherDigitalSignature(HashAlgorithm hash, AsymmetricCipher cipher)
         {
+            if (hash == null)
+                throw new ArgumentNullException("hash");
+
+            if (cipher == null)
+                throw new ArgumentNullException("cipher");
+
             this._hash = hash;
             this._cipher = cipher;
         }
@@ -32,7 +38,7 @@ namespace Renci.SshNet.Security.Cryptography
         /// <param name="input">The input.</param>
         /// <param name="signature">The signature.</param>
         /// <returns></returns>
-        public override bool VerifySignature(byte[] input, byte[] signature)
+        public override bool Verify(byte[] input, byte[] signature)
         {
             var sig = this._cipher.Decrypt(signature);
 
@@ -68,7 +74,7 @@ namespace Renci.SshNet.Security.Cryptography
         /// </summary>
         /// <param name="input">The input.</param>
         /// <returns></returns>
-        public override byte[] CreateSignature(byte[] input)
+        public override byte[] Sign(byte[] input)
         {
             //  Calculate hash value
             var hashData = this.Hash(input);
@@ -103,6 +109,7 @@ namespace Renci.SshNet.Security.Cryptography
 
         protected static List<byte> DerEncode(byte[] hashData)
         {
+            //  TODO:   Replace with DER Encoding
             //  TODO:   Replace with algorithm code
             var algorithm = new byte[] { 6, 5, 43, 14, 3, 2, 26 };
             var algorithmParams = new byte[] { 5, 0 };

+ 17 - 54
Renci.SshClient/Renci.SshNet/Security/Cryptography/Ciphers/RsaCipher.cs

@@ -16,56 +16,20 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
 
         private bool _isPrivate;
 
-        private BigInteger _exponent;
-
-        private BigInteger _modulus;
-        private BigInteger _d;
-        private BigInteger _dp;
-        private BigInteger _dq;
-        private BigInteger _inverseQ;
-        private BigInteger _p;
-        private BigInteger _q;
+        private RsaKey _key;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="RsaCipher"/> class.
         /// </summary>
-        /// <param name="exponent">The exponent.</param>
-        /// <param name="modulus">The modulus.</param>
-        public RsaCipher(BigInteger exponent, BigInteger modulus)
+        /// <param name="key">The RSA key.</param>
+        public RsaCipher(RsaKey key)
         {
-            //if (key == null)
-            //    throw new ArgumentNullException("key");
-            //this._publicKey = key;
-            this._exponent = exponent;
-            this._modulus = modulus;
-            this._isPrivate = false;
-        }
+            if (key == null)
+                throw new ArgumentNullException("key");
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="RsaCipher"/> 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="dq">The dq.</param>
-        /// <param name="inverseQ">The inverse Q.</param>
-        /// <param name="p">The p.</param>
-        /// <param name="q">The q.</param>
-        public RsaCipher(BigInteger exponent, BigInteger modulus, BigInteger d, BigInteger dp, BigInteger dq, BigInteger inverseQ, BigInteger p, BigInteger q)
-        {
-            //if (key == null)
-            //    throw new ArgumentNullException("key");
-            //this._privateKey = key;
-            this._exponent = exponent;
-            this._modulus = modulus;
-            this._d = d;
-            this._dp = dp;
-            this._dq = dq;
-            this._inverseQ = inverseQ;
-            this._p = p;
-            this._q = q;
-            this._isPrivate = true;
+            this._key = key;
+
+            this._isPrivate = !this._key.D.IsZero;
         }
 
         /// <summary>
@@ -101,7 +65,7 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
             {
                 BigInteger random = BigInteger.One;
 
-                var max = this._modulus - 1;
+                var max = this._key.Modulus - 1;
 
                 while (random <= BigInteger.One || random >= max)
                 {
@@ -112,29 +76,28 @@ namespace Renci.SshNet.Security.Cryptography.Ciphers
                     random = new BigInteger(bytesArray.Reverse().ToArray());
                 }
 
-                BigInteger blindedInput = BigInteger.PositiveMod((BigInteger.ModPow(random, this._exponent, this._modulus) * input), this._modulus);
+                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 % this._p), this._dp, this._p);
+                var mP = BigInteger.ModPow((blindedInput % this._key.P), this._key.DP, this._key.P);
 
                 // mQ = ((input Mod q) ^ dQ)) Mod q
-                var mQ = BigInteger.ModPow((blindedInput % this._q), this._dq, this._q);
+                var mQ = BigInteger.ModPow((blindedInput % this._key.Q), this._key.DQ, this._key.Q);
 
-                var h = BigInteger.PositiveMod(((mP - mQ) * this._inverseQ), this._p);
+                var h = BigInteger.PositiveMod(((mP - mQ) * this._key.InverseQ), this._key.P);
 
-                var m = h * this._q + mQ;
+                var m = h * this._key.Q + mQ;
 
-                BigInteger rInv = BigInteger.ModInverse(random, this._modulus);
+                BigInteger rInv = BigInteger.ModInverse(random, this._key.Modulus);
 
-                result = BigInteger.PositiveMod((m * rInv), this._modulus);
+                result = BigInteger.PositiveMod((m * rInv), this._key.Modulus);
             }
             else
             {
-                result = BigInteger.ModPow(input, this._exponent, this._modulus);
+                result = BigInteger.ModPow(input, this._key.Exponent, this._key.Modulus);
             }
             
             return result.ToByteArray().Reverse().ToArray();
         }
-
     }
 }

+ 2 - 2
Renci.SshClient/Renci.SshNet/Security/Cryptography/DigitalSignature.cs

@@ -17,13 +17,13 @@ namespace Renci.SshNet.Security.Cryptography
         /// <param name="input">The input.</param>
         /// <param name="signature">The signature.</param>
         /// <returns></returns>
-        public abstract bool VerifySignature(byte[] input, byte[] signature);
+        public abstract bool Verify(byte[] input, byte[] signature);
 
         /// <summary>
         /// Creates the signature.
         /// </summary>
         /// <param name="input">The input.</param>
         /// <returns></returns>
-        public abstract byte[] CreateSignature(byte[] input);
+        public abstract byte[] Sign(byte[] input);
     }
 }

+ 32 - 35
Renci.SshClient/Renci.SshNet/Security/Cryptography/DsaDigitalSignature.cs

@@ -13,30 +13,23 @@ namespace Renci.SshNet.Security.Cryptography
     /// </summary>
     public class DsaDigitalSignature : DigitalSignature
     {
-        private BigInteger _p;
-        private BigInteger _q;
-        private BigInteger _g;
-        private BigInteger _privateKey;
-        private BigInteger _publicKey;
+        private static RNGCryptoServiceProvider _randomizer = new System.Security.Cryptography.RNGCryptoServiceProvider();
+        
         private HashAlgorithm _hash;
 
+        private DsaKey _key;
+
         /// <summary>
         /// Initializes a new instance of the <see cref="DsaDigitalSignature"/> class.
         /// </summary>
-        /// <param name="p">The p.</param>
-        /// <param name="q">The q.</param>
-        /// <param name="g">The g.</param>
-        /// <param name="privateKey">The private key.</param>
-        /// <param name="publicKey">The public key.</param>
-        public DsaDigitalSignature(byte[] p, byte[] q, byte[] g, byte[] privateKey, byte[] publicKey)
+        /// <param name="key">The DSA key.</param>
+        public DsaDigitalSignature(DsaKey key)
         {
-            this._p = new BigInteger(p.Reverse().ToArray());
-            this._q = new BigInteger(q.Reverse().ToArray());
-            this._g = new BigInteger(g.Reverse().ToArray());
-            if (privateKey != null)
-                this._privateKey = new BigInteger(privateKey.Reverse().ToArray());
-            if (publicKey != null)
-                this._publicKey = new BigInteger(publicKey.Reverse().ToArray());
+            if (key == null)
+                throw new ArgumentNullException("key");
+
+            this._key = key;
+
             this._hash = new SHA1Hash();
         }
 
@@ -46,7 +39,7 @@ namespace Renci.SshNet.Security.Cryptography
         /// <param name="input">The input.</param>
         /// <param name="signature">The signature.</param>
         /// <returns></returns>
-        public override bool VerifySignature(byte[] input, byte[] signature)
+        public override bool Verify(byte[] input, byte[] signature)
         {
             var hashInput = this._hash.ComputeHash(input);
 
@@ -69,26 +62,26 @@ namespace Renci.SshNet.Security.Cryptography
             BigInteger s = new BigInteger(sBytes);
 
             //  Reject the signature if 0 < r < q or 0 < s < q is not satisfied.
-            if (r <= 0 || r >= this._q)
+            if (r <= 0 || r >= this._key.Q)
                 return false;
 
-            if (s <= 0 || s >= this._q)
+            if (s <= 0 || s >= this._key.Q)
                 return false;
 
             //  Calculate w = s−1 mod q
-            BigInteger w = BigInteger.ModInverse(s, this._q);
+            BigInteger w = BigInteger.ModInverse(s, this._key.Q);
 
             //  Calculate u1 = H(m)·w mod q
-            BigInteger u1 = hm * w % this._q;
+            BigInteger u1 = hm * w % this._key.Q;
 
             //  Calculate u2 = r * w mod q
-            BigInteger u2 = r * w % this._q;
+            BigInteger u2 = r * w % this._key.Q;
 
-            u1 = BigInteger.ModPow(this._g, u1, this._p);
-            u2 = BigInteger.ModPow(this._publicKey, u2, this._p);
+            u1 = BigInteger.ModPow(this._key.G, u1, this._key.P);
+            u2 = BigInteger.ModPow(this._key.Y, u2, this._key.P);
 
             //  Calculate v = ((g pow u1 * y pow u2) mod p) mod q
-            BigInteger v = ((u1 * u2) % this._p) % this._q;
+            BigInteger v = ((u1 * u2) % this._key.P) % this._key.Q;
 
             //  The signature is valid if v = r
             return v == r;
@@ -99,7 +92,7 @@ namespace Renci.SshNet.Security.Cryptography
         /// </summary>
         /// <param name="input">The input.</param>
         /// <returns></returns>
-        public override byte[] CreateSignature(byte[] input)
+        public override byte[] Sign(byte[] input)
         {
             var hashInput = this._hash.ComputeHash(input);
 
@@ -114,26 +107,30 @@ namespace Renci.SshNet.Security.Cryptography
 
                 do
                 {
-                    //  TODO:   Take random function to base class
+                    //  TODO:   Take random function to BigInteger
+
                     //  Generate a random per-message value k where 0 < k < q
                     do
                     {
-                        //k = new BigInteger(q.BitLength, random);
-                        k = BigInteger.Parse("980263959677973875983479554308083464979482795347", System.Globalization.NumberStyles.None, CultureInfo.InvariantCulture);
+                        var bytesArray = new byte[20];
+                        _randomizer.GetBytes(bytesArray);
+
+                        bytesArray[bytesArray.Length - 1] = (byte)(bytesArray[bytesArray.Length - 1] & 0x7F);   //  Ensure not a negative value
+                        k = new BigInteger(bytesArray.Reverse().ToArray());
                     }
-                    while (k <= 0 || k >= this._q);
+                    while (k <= 0 || k >= this._key.Q);
 
                     //  Calculate r = ((g pow k) mod p) mod q
-                    r = BigInteger.ModPow(this._g, k, this._p) % this._q;
+                    r = BigInteger.ModPow(this._key.G, k, this._key.P) % this._key.Q;
 
                     //      In the unlikely case that r = 0, start again with a different random k
                 } while (r.IsZero);
 
 
                 //  Calculate s = ((k pow −1)(H(m) + x*r)) mod q
-                k = (BigInteger.ModInverse(k, this._q) * (m + this._privateKey * r));
+                k = (BigInteger.ModInverse(k, this._key.Q) * (m + this._key.X * r));
 
-                s = k % this._q;
+                s = k % this._key.Q;
 
                 //  In the unlikely case that s = 0, start again with a different random k
             } while (s.IsZero);

+ 125 - 0
Renci.SshClient/Renci.SshNet/Security/Cryptography/DsaKey.cs

@@ -0,0 +1,125 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Renci.SshNet.Common;
+using Renci.SshNet.Security.Cryptography;
+
+namespace Renci.SshNet.Security
+{
+    /// <summary>
+    /// Contains DSA private and public key
+    /// </summary>
+    public class DsaKey : Key
+    {
+        /// <summary>
+        /// Gets public key Y.
+        /// </summary>
+        public BigInteger Y { get; private set; }
+
+        /// <summary>
+        /// Gets private key X.
+        /// </summary>
+        public BigInteger X { get; private set; }
+
+        /// <summary>
+        /// Gets the G.
+        /// </summary>
+        public BigInteger G { get; private set; }
+
+        /// <summary>
+        /// Gets the Q.
+        /// </summary>
+        public BigInteger Q { get; private set; }
+
+        /// <summary>
+        /// Gets the P.
+        /// </summary>
+        public BigInteger P { get; private set; }
+
+        private DigitalSignature _digitalSignature;
+        /// <summary>
+        /// Gets the digital signature.
+        /// </summary>
+        protected override DigitalSignature DigitalSignature
+        {
+            get
+            {
+                if (this._digitalSignature == null)
+                {
+                    this._digitalSignature = new DsaDigitalSignature(this);
+                }
+                return this._digitalSignature;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the public.
+        /// </summary>
+        /// <value>
+        /// The public.
+        /// </value>
+        public override BigInteger[] Public
+        {
+            get
+            {
+                return new BigInteger[] { this.P, this.Q, this.G, this.Y };
+            }
+            set
+            {
+                if (value.Length != 4)
+                    throw new InvalidOperationException("Invalid public key.");
+
+                this.P = value[0];
+                this.Q = value[1];
+                this.G = value[2];
+                this.Y = value[3];
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the private.
+        /// </summary>
+        /// <value>
+        /// The private.
+        /// </value>
+        protected override BigInteger[] Private
+        {
+            get
+            {
+                //return new BigInteger[] { this.P, this.Q, this.G, this.Y, this.X };
+                return new BigInteger[] { this.P, this.Q, this.G, this.X };
+            }
+            set
+            {
+                if (value.Length != 5)
+                    throw new InvalidOperationException("Invalid private key.");
+
+                this.P = value[0];
+                this.Q = value[1];
+                this.G = value[2];
+                this.Y = value[3];
+                this.X = value[4];
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="DsaKey"/> class.
+        /// </summary>
+        public DsaKey()
+            : base()
+        {
+
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="DsaKey"/> class.
+        /// </summary>
+        /// <param name="data">DER encoded private key data.</param>
+        public DsaKey(byte[] data)
+            : base(data)
+        {
+
+        }
+    }
+}

+ 87 - 0
Renci.SshClient/Renci.SshNet/Security/Cryptography/Key.cs

@@ -0,0 +1,87 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Renci.SshNet.Common;
+using Renci.SshNet.Security.Cryptography;
+
+namespace Renci.SshNet.Security
+{
+    /// <summary>
+    /// Base class for asymmetric cipher algorithms
+    /// </summary>
+    public abstract class Key
+    {
+        /// <summary>
+        /// Gets the key specific digital signature.
+        /// </summary>
+        protected abstract DigitalSignature DigitalSignature { get; }
+
+        /// <summary>
+        /// Gets or sets the public key.
+        /// </summary>
+        /// <value>
+        /// The public.
+        /// </value>
+        public abstract BigInteger[] Public { get; set; }
+
+        /// <summary>
+        /// Gets or sets the private key.
+        /// </summary>
+        /// <value>
+        /// The private.
+        /// </value>
+        protected abstract BigInteger[] Private { get; set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Key"/> class.
+        /// </summary>
+        /// <param name="data">DER encoded private key data.</param>
+        public Key(byte[] data)
+        {
+            if (data == null)
+                throw new ArgumentNullException("data");
+
+            var der = new DerData(data);
+            var version = der.ReadBigInteger();
+
+            var keys = new List<BigInteger>();
+            while (!der.IsEndOfData)
+            {
+                keys.Add(der.ReadBigInteger());
+            }
+
+            this.Private = keys.ToArray();
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Key"/> class.
+        /// </summary>
+        public Key()
+            : base()
+        {
+
+        }
+
+        /// <summary>
+        /// Signs the specified data with the key.
+        /// </summary>
+        /// <param name="data">The data to sign.</param>
+        /// <returns>Signed data.</returns>
+        public byte[] Sign(byte[] data)
+        {
+            return this.DigitalSignature.Sign(data);
+        }
+
+        /// <summary>
+        /// Verifies the signature.
+        /// </summary>
+        /// <param name="data">The data to verify.</param>
+        /// <param name="signature">The signature to verify against.</param>
+        /// <returns></returns>
+        public bool VerifySignature(byte[] data, byte[] signature)
+        {
+            return this.DigitalSignature.Verify(data, signature);
+        }
+    }
+}

+ 3 - 20
Renci.SshClient/Renci.SshNet/Security/Cryptography/RsaDigitalSignature.cs

@@ -16,26 +16,9 @@ namespace Renci.SshNet.Security.Cryptography
         /// <summary>
         /// Initializes a new instance of the <see cref="RsaDigitalSignature"/> class.
         /// </summary>
-        /// <param name="exponent">The exponent.</param>
-        /// <param name="modulus">The modulus.</param>
-        /// <param name="d">The D value.</param>
-        /// <param name="dp">The DP value.</param>
-        /// <param name="dq">The DQ value.</param>
-        /// <param name="inverseQ">The InverseQ value.</param>
-        /// <param name="p">The P value.</param>
-        /// <param name="q">The Q value.</param>
-        public RsaDigitalSignature(byte[] exponent, byte[] modulus, byte[] d, byte[] dp, byte[] dq, byte[] inverseQ, byte[] p, byte[] q)
-            : base(new SHA1Hash(), new RsaCipher(new BigInteger(exponent.Reverse().ToArray()), new BigInteger(modulus.Reverse().ToArray()), new BigInteger(d.Reverse().ToArray()), new BigInteger(dp.Reverse().ToArray()), new BigInteger(dq.Reverse().ToArray()), new BigInteger(inverseQ.Reverse().ToArray()), new BigInteger(p.Reverse().ToArray()), new BigInteger(q.Reverse().ToArray())))
-        {
-        }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="RsaDigitalSignature"/> class.
-        /// </summary>
-        /// <param name="exponent">The exponent.</param>
-        /// <param name="modulus">The modulus.</param>
-        public RsaDigitalSignature(byte[] exponent, byte[] modulus)
-            : base(new SHA1Hash(), new RsaCipher(new BigInteger(exponent.Reverse().ToArray()), new BigInteger(modulus.Reverse().ToArray())))
+        /// <param name="rsaKey">The RSA key.</param>
+        public RsaDigitalSignature(RsaKey rsaKey)
+            : base(new SHA1Hash(), new RsaCipher(rsaKey))
         {
         }
     }

+ 139 - 0
Renci.SshClient/Renci.SshNet/Security/Cryptography/RsaKey.cs

@@ -0,0 +1,139 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Renci.SshNet.Common;
+using Renci.SshNet.Security.Cryptography;
+
+namespace Renci.SshNet.Security
+{
+    /// <summary>
+    /// Contains RSA private and public key
+    /// </summary>
+    public class RsaKey : Key
+    {
+        /// <summary>
+        /// Gets the modulus.
+        /// </summary>
+        public BigInteger Modulus { get; private set; }
+
+        /// <summary>
+        /// Gets the exponent.
+        /// </summary>
+        public BigInteger Exponent { get; private set; }
+
+        /// <summary>
+        /// Gets the D.
+        /// </summary>
+        public BigInteger D { get; private set; }
+
+        /// <summary>
+        /// Gets the P.
+        /// </summary>
+        public BigInteger P { get; private set; }
+
+        /// <summary>
+        /// Gets the Q.
+        /// </summary>
+        public BigInteger Q { get; private set; }
+
+        /// <summary>
+        /// Gets the DP.
+        /// </summary>
+        public BigInteger DP { get; private set; }
+
+        /// <summary>
+        /// Gets the DQ.
+        /// </summary>
+        public BigInteger DQ { get; private set; }
+
+        /// <summary>
+        /// Gets the inverse Q.
+        /// </summary>
+        public BigInteger InverseQ { get; private set; }
+
+        private DigitalSignature _digitalSignature;
+        /// <summary>
+        /// Gets the digital signature.
+        /// </summary>
+        protected override DigitalSignature DigitalSignature
+        {
+            get
+            {
+                if (this._digitalSignature == null)
+                {
+                    this._digitalSignature = new RsaDigitalSignature(this);
+                }
+                return this._digitalSignature;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the public.
+        /// </summary>
+        /// <value>
+        /// The public.
+        /// </value>
+        public override BigInteger[] Public
+        {
+            get
+            {
+                return new BigInteger[] { this.Exponent, this.Modulus };
+            }
+            set
+            {
+                if (value.Length != 2)
+                    throw new InvalidOperationException("Invalid private key.");
+
+                this.Exponent = value[0];
+                this.Modulus = value[1];
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the private.
+        /// </summary>
+        /// <value>
+        /// The private.
+        /// </value>
+        protected override BigInteger[] Private
+        {
+            get
+            {
+                return new BigInteger[] { this.Modulus, this.Exponent, this.D, this.P, this.Q, this.DP, this.DQ, this.InverseQ };
+            }
+            set
+            {
+                if (value.Length != 8)
+                    throw new InvalidOperationException("Invalid private key.");
+
+                this.Modulus = value[0];
+                this.Exponent = value[1];
+                this.D = value[2];
+                this.P = value[3];
+                this.Q = value[4];
+                this.DP = value[5];
+                this.DQ = value[6];
+                this.InverseQ = value[7];
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RsaKey"/> class.
+        /// </summary>
+        public RsaKey()
+        {
+
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RsaKey"/> class.
+        /// </summary>
+        /// <param name="data">DER encoded private key data.</param>
+        public RsaKey(byte[] data)
+            : base(data)
+        {
+
+        }
+    }
+}

+ 49 - 0
Renci.SshClient/Renci.SshNet/Security/HostAlgorithm.cs

@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Renci.SshNet.Common;
+using Renci.SshNet.Security.Cryptography;
+
+namespace Renci.SshNet.Security
+{
+    /// <summary>
+    /// Base class for SSH host algorithms.
+    /// </summary>
+    public abstract class HostAlgorithm
+    {
+        /// <summary>
+        /// Gets the host key name.
+        /// </summary>
+        public string Name { get; private set; }
+
+        /// <summary>
+        /// Gets the host key data.
+        /// </summary>
+        public abstract byte[] Data { get; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="HostAlgorithm"/> class.
+        /// </summary>
+        /// <param name="name">The host key name.</param>
+        public HostAlgorithm(string name)
+        {
+            this.Name = name;
+        }
+
+        /// <summary>
+        /// Signs the specified data.
+        /// </summary>
+        /// <param name="data">The data.</param>
+        /// <returns></returns>
+        public abstract byte[] Sign(byte[] data);
+
+        /// <summary>
+        /// Verifies the signature.
+        /// </summary>
+        /// <param name="data">The data.</param>
+        /// <param name="signature">The signature.</param>
+        /// <returns></returns>
+        public abstract bool VerifySignature(byte[] data, byte[] signature);
+    }
+}

+ 4 - 3
Renci.SshClient/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs

@@ -7,6 +7,7 @@ using Renci.SshNet.Messages.Transport;
 using System.Diagnostics;
 using Renci.SshNet.Messages;
 using Renci.SshNet.Common;
+using Renci.SshNet.Security.Cryptography;
 
 namespace Renci.SshNet.Security
 {
@@ -72,6 +73,8 @@ namespace Renci.SshNet.Security
         {
             var exchangeHash = this.CalculateHash();
 
+            //  TODO:   See how to improve this area
+
             var bytes = this._hostKey;
 
             var length = (uint)(this._hostKey[0] << 24 | this._hostKey[1] << 16 | this._hostKey[2] << 8 | this._hostKey[3]);
@@ -80,9 +83,7 @@ namespace Renci.SshNet.Security
 
             var data = bytes.Skip(4 + algorithmName.Length);
 
-            CryptoPublicKey key = this.Session.ConnectionInfo.HostKeyAlgorithms[algorithmName].CreateInstance<CryptoPublicKey>();
-
-            key.Load(data);
+            var key = this.Session.ConnectionInfo.HostKeyAlgorithms[algorithmName](this._hostKey);
 
             return key.VerifySignature(exchangeHash, this._signature);
         }

+ 165 - 0
Renci.SshClient/Renci.SshNet/Security/KeyHostAlgorithm.cs

@@ -0,0 +1,165 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Renci.SshNet.Common;
+using Renci.SshNet.Security.Cryptography;
+
+namespace Renci.SshNet.Security
+{
+    /// <summary>
+    /// Implements key support for host algorithm.
+    /// </summary>
+    public class KeyHostAlgorithm : HostAlgorithm
+    {
+        private Key _key;
+
+        /// <summary>
+        /// Gets the public key data.
+        /// </summary>
+        public override byte[] Data
+        {
+            get
+            {
+                return new SshKeyData(this.Name, this._key.Public).GetBytes();
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="KeyHostAlgorithm"/> class.
+        /// </summary>
+        /// <param name="name">Host key name.</param>
+        /// <param name="key">Host key.</param>
+        public KeyHostAlgorithm(string name, Key key)
+            : base(name)
+        {
+            this._key = key;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="HostAlgorithm"/> class.
+        /// </summary>
+        /// <param name="name">Host key name.</param>
+        /// <param name="key">Host key.</param>
+        /// <param name="data">Host key encoded data.</param>
+        public KeyHostAlgorithm(string name, Key key, byte[] data)
+            : base(name)
+        {
+            this._key = key;
+
+            var sshKey = new SshKeyData();
+            sshKey.Load(data);
+            this._key.Public = sshKey.Keys;
+        }
+
+        /// <summary>
+        /// Signs the specified data.
+        /// </summary>
+        /// <param name="data">The data.</param>
+        /// <returns></returns>
+        public override byte[] Sign(byte[] data)
+        {
+            return new SignatureKeyData(this.Name, this._key.Sign(data)).GetBytes().ToArray();
+        }
+
+        /// <summary>
+        /// Verifies the signature.
+        /// </summary>
+        /// <param name="data">The data.</param>
+        /// <param name="signature">The signature.</param>
+        /// <returns></returns>
+        public override bool VerifySignature(byte[] data, byte[] signature)
+        {
+            var signatureData = new SignatureKeyData();
+            signatureData.Load(signature);
+
+            return this._key.VerifySignature(data, signatureData.Signature);
+        }
+
+        private class SshKeyData : SshData
+        {
+            public BigInteger[] Keys { get; private set; }
+
+            public string Name { get; private set; }
+
+            public SshKeyData()
+            {
+
+            }
+
+            public SshKeyData(string name, params BigInteger[] keys)
+            {
+                this.Name = name;
+                this.Keys = keys;
+            }
+
+            protected override void LoadData()
+            {
+                this.Name = this.ReadString();
+                var keys = new List<BigInteger>();
+                while (!this.IsEndOfData)
+                {
+                    keys.Add(this.ReadBigInt());
+                }
+                this.Keys = keys.ToArray();
+            }
+
+            protected override void SaveData()
+            {
+                this.Write(this.Name);
+                foreach (var key in this.Keys)
+                {
+                    this.Write(key);
+                }
+            }
+        }
+
+        private class SignatureKeyData : SshData
+        {
+            /// <summary>
+            /// Gets or sets the name of the algorithm.
+            /// </summary>
+            /// <value>
+            /// The name of the algorithm.
+            /// </value>
+            public string AlgorithmName { get; private set; }
+
+            /// <summary>
+            /// Gets or sets the signature.
+            /// </summary>
+            /// <value>
+            /// The signature.
+            /// </value>
+            public byte[] Signature { get; private set; }
+
+            public SignatureKeyData()
+            {
+
+            }
+
+            public SignatureKeyData(string name, byte[] signature)
+            {
+                this.AlgorithmName = name;
+                this.Signature = signature;
+            }
+
+            /// <summary>
+            /// Called when type specific data need to be loaded.
+            /// </summary>
+            protected override void LoadData()
+            {
+                this.AlgorithmName = this.ReadString();
+                this.Signature = this.ReadBinaryString();
+            }
+
+            /// <summary>
+            /// Called when type specific data need to be saved.
+            /// </summary>
+            protected override void SaveData()
+            {
+                this.Write(this.AlgorithmName);
+                this.WriteBinaryString(this.Signature);
+            }
+        }
+    }
+}

部分文件因为文件数量过多而无法显示