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);
}
}
}
}