using System; using System.Linq; using System.Text; using Renci.SshNet.Messages.Transport; using Renci.SshNet.Common; namespace Renci.SshNet.Security { /// /// Represents base class for Diffie Hellman key exchange algorithm /// public abstract class KeyExchangeDiffieHellman : KeyExchange { /// /// Specifies key exchange group number. /// protected BigInteger _group; /// /// Specifies key exchange prime number. /// protected BigInteger _prime; /// /// Specifies client payload /// protected byte[] _clientPayload; /// /// Specifies server payload /// protected byte[] _serverPayload; /// /// Specifies client exchange number. /// protected BigInteger _clientExchangeValue; /// /// Specifies server exchange number. /// protected BigInteger _serverExchangeValue; /// /// Specifies random generated number. /// protected BigInteger _randomValue; /// /// Specifies host key data. /// protected byte[] _hostKey; /// /// Specifies signature data. /// protected byte[] _signature; /// /// Validates the exchange hash. /// /// /// true if exchange hash is valid; otherwise false. /// protected override bool ValidateExchangeHash() { var exchangeHash = this.CalculateHash(); var length = (uint)(this._hostKey[0] << 24 | this._hostKey[1] << 16 | this._hostKey[2] << 8 | this._hostKey[3]); var algorithmName = Encoding.UTF8.GetString(this._hostKey, 4, (int)length); var key = this.Session.ConnectionInfo.HostKeyAlgorithms[algorithmName](this._hostKey); this.Session.ConnectionInfo.CurrentHostKeyAlgorithm = algorithmName; if (this.CanTrustHostKey(key)) { return key.VerifySignature(exchangeHash, this._signature); } return false; } /// /// Starts key exchange algorithm /// /// The session. /// Key exchange init message. public override void Start(Session session, KeyExchangeInitMessage message) { base.Start(session, message); this._serverPayload = message.GetBytes().ToArray(); this._clientPayload = this.Session.ClientInitMessage.GetBytes().ToArray(); } /// /// Populates the client exchange value. /// protected void PopulateClientExchangeValue() { if (this._group.IsZero) throw new ArgumentNullException("_group"); if (this._prime.IsZero) throw new ArgumentNullException("_prime"); var bitLength = this._prime.BitLength; do { this._randomValue = BigInteger.Random(bitLength); this._clientExchangeValue = BigInteger.ModPow(this._group, this._randomValue, this._prime); } while (this._clientExchangeValue < 1 || this._clientExchangeValue > ((this._prime - 1))); } /// /// Handles the server DH reply message. /// /// The host key. /// The server exchange value. /// The signature. protected virtual void HandleServerDhReply(byte[] hostKey, BigInteger serverExchangeValue, byte[] signature) { this._serverExchangeValue = serverExchangeValue; this._hostKey = hostKey; this.SharedKey = BigInteger.ModPow(serverExchangeValue, this._randomValue, this._prime); this._signature = signature; } } }