using Renci.SshNet.Common; using Renci.SshNet.Messages.Transport; namespace Renci.SshNet.Security { internal abstract class KeyExchangeDiffieHellmanGroupShaBase : KeyExchangeDiffieHellman { /// /// Gets the group prime. /// /// /// The group prime. /// public abstract BigInteger GroupPrime { get; } /// /// Starts key exchange algorithm. /// /// The session. /// Key exchange init message. public override void Start(Session session, KeyExchangeInitMessage message) { base.Start(session, message); Session.RegisterMessage("SSH_MSG_KEXDH_REPLY"); Session.KeyExchangeDhReplyMessageReceived += Session_KeyExchangeDhReplyMessageReceived; _prime = GroupPrime; _group = new BigInteger(new byte[] { 2 }); PopulateClientExchangeValue(); SendMessage(new KeyExchangeDhInitMessage(_clientExchangeValue)); } /// /// Finishes key exchange algorithm. /// public override void Finish() { base.Finish(); Session.KeyExchangeDhReplyMessageReceived -= Session_KeyExchangeDhReplyMessageReceived; } /// /// Calculates key exchange hash value. /// /// /// Key exchange hash. /// protected override byte[] CalculateHash() { var keyExchangeHashData = new KeyExchangeHashData { ClientVersion = Session.ClientVersion, ServerVersion = Session.ServerVersion, ClientPayload = _clientPayload, ServerPayload = _serverPayload, HostKey = _hostKey, ClientExchangeValue = _clientExchangeValue, ServerExchangeValue = _serverExchangeValue, SharedKey = SharedKey, }; return Hash(keyExchangeHashData.GetBytes()); } private void Session_KeyExchangeDhReplyMessageReceived(object sender, MessageEventArgs e) { var message = e.Message; // Unregister message once received Session.UnRegisterMessage("SSH_MSG_KEXDH_REPLY"); HandleServerDhReply(message.HostKey, message.F, message.Signature); // When SSH_MSG_KEXDH_REPLY received key exchange is completed Finish(); } } }