using System; using Renci.SshNet.Common; using Renci.SshNet.Messages; using Renci.SshNet.Messages.Transport; namespace Renci.SshNet.Security { /// /// Represents "diffie-hellman-group1-sha1" algorithm implementation. /// public abstract class KeyExchangeDiffieHellmanGroupSha1 : KeyExchangeDiffieHellman { /// /// Gets the group prime. /// /// /// The group prime. /// public abstract BigInteger GroupPrime { get; } /// /// Calculates key exchange hash value. /// /// /// Key exchange hash. /// protected override byte[] CalculateHash() { var hashData = new _ExchangeHashData { ClientVersion = Session.ClientVersion, ServerVersion = Session.ServerVersion, ClientPayload = _clientPayload, ServerPayload = _serverPayload, HostKey = _hostKey, ClientExchangeValue = _clientExchangeValue, ServerExchangeValue = _serverExchangeValue, SharedKey = SharedKey, }.GetBytes(); return Hash(hashData); } /// /// 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; } 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(); } private class _ExchangeHashData : SshData { private byte[] _serverVersion; private byte[] _clientVersion; private byte[] _clientExchangeValue; private byte[] _serverExchangeValue; private byte[] _sharedKey; public string ServerVersion { private get { return Utf8.GetString(_serverVersion, 0, _serverVersion.Length); } set { _serverVersion = Utf8.GetBytes(value); } } public string ClientVersion { private get { return Utf8.GetString(_clientVersion, 0, _clientVersion.Length); } set { _clientVersion = Utf8.GetBytes(value); } } public byte[] ClientPayload { get; set; } public byte[] ServerPayload { get; set; } public byte[] HostKey { get; set; } public BigInteger ClientExchangeValue { private get { return _clientExchangeValue.ToBigInteger(); } set { _clientExchangeValue = value.ToByteArray().Reverse(); } } public BigInteger ServerExchangeValue { private get { return _serverExchangeValue.ToBigInteger(); } set { _serverExchangeValue = value.ToByteArray().Reverse(); } } public BigInteger SharedKey { private get { return _sharedKey.ToBigInteger(); } set { _sharedKey = value.ToByteArray().Reverse(); } } /// /// Gets the size of the message in bytes. /// /// /// The size of the messages in bytes. /// protected override int BufferCapacity { get { var capacity = base.BufferCapacity; capacity += 4; // ClientVersion length capacity += _clientVersion.Length; // ClientVersion capacity += 4; // ServerVersion length capacity += _serverVersion.Length; // ServerVersion capacity += 4; // ClientPayload length capacity += ClientPayload.Length; // ClientPayload capacity += 4; // ServerPayload length capacity += ServerPayload.Length; // ServerPayload capacity += 4; // HostKey length capacity += HostKey.Length; // HostKey capacity += 4; // ClientExchangeValue length capacity += _clientExchangeValue.Length; // ClientExchangeValue capacity += 4; // ServerExchangeValue length capacity += _serverExchangeValue.Length; // ServerExchangeValue capacity += 4; // SharedKey length capacity += _sharedKey.Length; // SharedKey return capacity; } } protected override void LoadData() { throw new NotImplementedException(); } protected override void SaveData() { WriteBinaryString(_clientVersion); WriteBinaryString(_serverVersion); WriteBinaryString(ClientPayload); WriteBinaryString(ServerPayload); WriteBinaryString(HostKey); WriteBinaryString(_clientExchangeValue); WriteBinaryString(_serverExchangeValue); WriteBinaryString(_sharedKey); } } } }